{"version":3,"file":"SidecarService_EXPERIMENTAL.mjs","sources":["../../../src/services/SidecarService_EXPERIMENTAL.ts"],"sourcesContent":["import * as H from 'history';\nimport { pick } from 'lodash';\nimport { BehaviorSubject, map, Observable } from 'rxjs';\n\nimport { reportInteraction } from '../analytics/utils';\nimport { config } from '../config';\n\nimport { HistoryWrapper, locationService as mainLocationService, LocationService } from './LocationService';\n\n// Only allow sidecar to be opened on these routes. It does not seem to make sense to keep the sidecar opened on\n// config/admin pages for example.\n// At this moment let's be restrictive about where the sidecar can show and add more routes if there is a need.\nconst ALLOW_ROUTES = [\n  /(^\\/d\\/)/, // dashboards\n  /^\\/explore/, // explore + explore metrics\n  /^\\/a\\/[^\\/]+/, // app plugins\n  /^\\/alerting/,\n];\n\n/**\n * This is a service that handles state and operation of a sidecar feature (sideview to render a second app in grafana).\n * At this moment this is highly experimental and if used should be understood to break easily with newer versions.\n * None of this functionality works without a feature toggle `appSidecar` being enabled.\n *\n * Right now this being in a single service is more of a practical tradeoff for easier isolation in the future these\n * APIs may be integrated into other services or features like app extensions, plugin system etc.\n *\n * @experimental\n */\nexport class SidecarService_EXPERIMENTAL {\n  private _initialContext: BehaviorSubject<unknown | undefined>;\n\n  private sidecarLocationService: LocationService;\n  private mainLocationService: LocationService;\n\n  // If true we don't close the sidecar when user navigates to another app or part of Grafana from where the sidecar\n  // was opened.\n  private follow = false;\n\n  // Keep track of where the sidecar was originally opened for autoclose behaviour.\n  private mainLocationWhenOpened: string | undefined;\n\n  private mainOnAllowedRoute = false;\n\n  constructor(mainLocationService: LocationService) {\n    this._initialContext = new BehaviorSubject<unknown | undefined>(undefined);\n    this.mainLocationService = mainLocationService;\n    this.sidecarLocationService = new HistoryWrapper(\n      createLocationStorageHistory({ storageKey: 'grafana.sidecar.history' })\n    );\n    this.handleMainLocationChanges();\n  }\n\n  private assertFeatureEnabled() {\n    if (!config.featureToggles.appSidecar) {\n      console.warn('The `appSidecar` feature toggle is not enabled, doing nothing.');\n      return false;\n    }\n\n    return true;\n  }\n\n  private updateMainLocationWhenOpened() {\n    const pathname = this.mainLocationService.getLocation().pathname;\n    for (const route of ALLOW_ROUTES) {\n      const match = pathname.match(route)?.[0];\n      if (match) {\n        this.mainLocationWhenOpened = match;\n        return;\n      }\n    }\n  }\n\n  /**\n   * Every time the main location changes we check if we should keep the sidecar open or close it based on list\n   * of allowed routes and also based on the follow flag when opening the app.\n   */\n  private handleMainLocationChanges() {\n    this.mainOnAllowedRoute = ALLOW_ROUTES.some((prefix) =>\n      this.mainLocationService.getLocation().pathname.match(prefix)\n    );\n\n    this.mainLocationService.getLocationObservable().subscribe((location) => {\n      this.mainOnAllowedRoute = ALLOW_ROUTES.some((prefix) => location.pathname.match(prefix));\n\n      if (!this.activePluginId) {\n        return;\n      }\n\n      if (!this.mainOnAllowedRoute) {\n        this.closeApp();\n        return;\n      }\n\n      // We check if we moved to some other app or part of grafana from where we opened the sidecar.\n      const isTheSameLocation = Boolean(\n        this.mainLocationWhenOpened && location.pathname.startsWith(this.mainLocationWhenOpened)\n      );\n\n      if (!(isTheSameLocation || this.follow)) {\n        this.closeApp();\n      }\n    });\n  }\n\n  /**\n   * Get current app id of the app in sidecar. This is most probably provisional. In the future\n   * this should be driven by URL addressing so that routing for the apps don't change. Useful just internally\n   * to decide which app to render.\n   *\n   * @experimental\n   */\n  get activePluginIdObservable() {\n    return this.sidecarLocationService.getLocationObservable().pipe(\n      map((val) => {\n        return getPluginIdFromUrl(val?.pathname || '');\n      })\n    );\n  }\n\n  /**\n   * Get initial context which is whatever data was passed when calling the 'openApp' function. This is meant as\n   * a way for the app to initialize it's state based on some context that is passed to it from the primary app.\n   *\n   * @experimental\n   */\n  get initialContextObservable() {\n    return this._initialContext.asObservable();\n  }\n\n  // Get the current value of the subject, this is needed if we want the value immediately. For example if used in\n  // hook in react with useObservable first render would return undefined even if the behaviourSubject has some\n  // value which will be emitted in the next tick and thus next rerender.\n  get initialContext() {\n    return this._initialContext.getValue();\n  }\n\n  /**\n   * @experimental\n   */\n  get activePluginId() {\n    return getPluginIdFromUrl(this.sidecarLocationService.getLocation().pathname);\n  }\n\n  getLocationService() {\n    return this.sidecarLocationService;\n  }\n\n  /**\n   * Opens an app in a sidecar. You can also pass some context object that will be then available to the app.\n   * @deprecated\n   * @experimental\n   */\n  openApp(pluginId: string, context?: unknown) {\n    if (!(this.assertFeatureEnabled() && this.mainOnAllowedRoute)) {\n      return;\n    }\n    this._initialContext.next(context);\n    this.openAppV3({ pluginId, follow: false });\n  }\n\n  /**\n   * Opens an app in a sidecar. You can also relative path inside the app to open.\n   * @deprecated\n   * @experimental\n   */\n  openAppV2(pluginId: string, path?: string) {\n    this.openAppV3({ pluginId, path, follow: false });\n  }\n\n  /**\n   * Opens an app in a sidecar. You can also relative path inside the app to open.\n   * @param options.pluginId Plugin ID of the app to open\n   * @param options.path Relative path inside the app to open\n   * @param options.follow If true, the sidecar will stay open even if the main location change to another app or\n   *   Grafana section\n   *\n   * @experimental\n   */\n  openAppV3(options: { pluginId: string; path?: string; follow?: boolean }) {\n    if (!(this.assertFeatureEnabled() && this.mainOnAllowedRoute)) {\n      return;\n    }\n\n    this.follow = options.follow || false;\n\n    this.updateMainLocationWhenOpened();\n    this.sidecarLocationService.push({ pathname: `/a/${options.pluginId}${options.path || ''}` });\n    reportInteraction('sidecar_service_open_app', { pluginId: options.pluginId, follow: options.follow });\n  }\n\n  /**\n   * @experimental\n   */\n  closeApp() {\n    if (!this.assertFeatureEnabled()) {\n      return;\n    }\n\n    this.follow = false;\n    this.mainLocationWhenOpened = undefined;\n    this._initialContext.next(undefined);\n    this.sidecarLocationService.replace({ pathname: '/' });\n\n    reportInteraction('sidecar_service_close_app');\n  }\n\n  /**\n   * This is mainly useful inside an app extensions which are executed outside the main app context but can work\n   * differently depending on whether their app is currently rendered or not.\n   *\n   * This is also true only in case a sidecar is opened. In other cases, just to check if a single app is opened\n   * probably does not make sense.\n   *\n   * This means these are the states and the result of this function:\n   * Single app is opened: false (may seem strange from considering the function name, but the main point of\n   *   this is to recognize when the app needs to do specific alteration in context of running next to second app)\n   * 2 apps are opened and pluginId is the one in the main window: true\n   * 2 apps are opened and pluginId is the one in the sidecar window: true\n   * 2 apps are opened and pluginId is not one of those: false\n   *\n   * @experimental\n   */\n  isAppOpened(pluginId: string) {\n    if (!this.assertFeatureEnabled()) {\n      return false;\n    }\n\n    const result = !!(this.activePluginId && (this.activePluginId === pluginId || getMainAppPluginId() === pluginId));\n    reportInteraction('sidecar_service_is_app_opened', { pluginId, isOpened: result });\n    return result;\n  }\n}\n\nconst pluginIdUrlRegex = /a\\/([^\\/]+)/;\nfunction getPluginIdFromUrl(url: string) {\n  return url.match(pluginIdUrlRegex)?.[1];\n}\n\n// The app plugin that is \"open\" in the main Grafana view\nfunction getMainAppPluginId() {\n  // TODO: not great but we have to get a handle on the other locationService used for the main view and easiest way\n  //   right now is through this global singleton\n  const { pathname } = mainLocationService.getLocation();\n\n  // A naive way to sort of simulate core features being an app and having an appID\n  let mainApp = getPluginIdFromUrl(pathname);\n  if (!mainApp && pathname.match(/\\/explore/)) {\n    mainApp = 'explore';\n  }\n\n  if (!mainApp && pathname.match(/\\/d\\//)) {\n    mainApp = 'dashboards';\n  }\n\n  return mainApp || 'unknown';\n}\n\ntype LocalStorageHistoryOptions = {\n  storageKey: string;\n};\n\ninterface LocationStorageHistory extends H.MemoryHistory {\n  getLocationObservable(): Observable<H.Location | undefined>;\n}\n\n/**\n * Simple wrapper over the memory history that persists the location in the localStorage.\n *\n * @param options\n */\nfunction createLocationStorageHistory(options: LocalStorageHistoryOptions): LocationStorageHistory {\n  const storedLocation = localStorage.getItem(options.storageKey);\n  const initialEntry = storedLocation ? JSON.parse(storedLocation) : '/';\n  const locationSubject = new BehaviorSubject<H.Location | undefined>(initialEntry);\n  const memoryHistory = H.createMemoryHistory({ initialEntries: [initialEntry] });\n\n  let currentLocation = memoryHistory.location;\n\n  function maybeUpdateLocation() {\n    if (memoryHistory.location !== currentLocation) {\n      localStorage.setItem(\n        options.storageKey,\n        JSON.stringify(pick(memoryHistory.location, 'pathname', 'search', 'hash'))\n      );\n      currentLocation = memoryHistory.location;\n      locationSubject.next(memoryHistory.location);\n    }\n  }\n\n  // This creates a sort of proxy over the memory location just to add the localStorage persistence and the location\n  // observer. We could achieve the same effect by a listener but that would create a memory leak as there would be no\n  // reasonable way to unsubcribe the listener later on.\n  // Another issue is that react router for some reason does not care about proper `this` binding and just calls these\n  // as normal functions. So if this were to be a class we would still need to bind each of these methods to the\n  // instance so at that moment this just seems easier.\n  return {\n    ...memoryHistory,\n    // Getter aren't destructured as getter but as values, so they have to be still here even though we are not\n    // modifying them.\n    get index() {\n      return memoryHistory.index;\n    },\n    get entries() {\n      return memoryHistory.entries;\n    },\n    get length() {\n      return memoryHistory.length;\n    },\n    get action() {\n      return memoryHistory.action;\n    },\n    get location() {\n      return memoryHistory.location;\n    },\n    push(location: H.Path | H.LocationDescriptor<H.LocationState>, state?: H.LocationState) {\n      memoryHistory.push(location, state);\n      maybeUpdateLocation();\n    },\n    replace(location: H.Path | H.LocationDescriptor<H.LocationState>, state?: H.LocationState) {\n      memoryHistory.replace(location, state);\n      maybeUpdateLocation();\n    },\n    go(n: number) {\n      memoryHistory.go(n);\n      maybeUpdateLocation();\n    },\n    goBack() {\n      memoryHistory.goBack();\n      maybeUpdateLocation();\n    },\n    goForward() {\n      memoryHistory.goForward();\n      maybeUpdateLocation();\n    },\n    getLocationObservable() {\n      return locationSubject.asObservable();\n    },\n  };\n}\n\nexport const sidecarServiceSingleton_EXPERIMENTAL = new SidecarService_EXPERIMENTAL(mainLocationService);\n"],"names":["mainLocationService"],"mappings":"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"}