mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Sidecar: Specify where it can be opened and when it automatically closes (#96683)
This commit is contained in:
parent
fd3ecacd05
commit
58e9f22c1b
@ -1,5 +1,6 @@
|
|||||||
import * as H from 'history';
|
import * as H from 'history';
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
import { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data';
|
import { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data';
|
||||||
import { attachDebugger, createLogger } from '@grafana/ui';
|
import { attachDebugger, createLogger } from '@grafana/ui';
|
||||||
@ -21,6 +22,7 @@ export interface LocationService {
|
|||||||
getHistory: () => H.History;
|
getHistory: () => H.History;
|
||||||
getSearch: () => URLSearchParams;
|
getSearch: () => URLSearchParams;
|
||||||
getSearchObject: () => UrlQueryMap;
|
getSearchObject: () => UrlQueryMap;
|
||||||
|
getLocationObservable: () => Observable<H.Location>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is from the old LocationSrv interface
|
* This is from the old LocationSrv interface
|
||||||
@ -31,6 +33,7 @@ export interface LocationService {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
export class HistoryWrapper implements LocationService {
|
export class HistoryWrapper implements LocationService {
|
||||||
private readonly history: H.History;
|
private readonly history: H.History;
|
||||||
|
private locationObservable: BehaviorSubject<H.Location>;
|
||||||
|
|
||||||
constructor(history?: H.History) {
|
constructor(history?: H.History) {
|
||||||
// If no history passed create an in memory one if being called from test
|
// If no history passed create an in memory one if being called from test
|
||||||
@ -40,6 +43,12 @@ export class HistoryWrapper implements LocationService {
|
|||||||
? H.createMemoryHistory({ initialEntries: ['/'] })
|
? H.createMemoryHistory({ initialEntries: ['/'] })
|
||||||
: H.createBrowserHistory({ basename: config.appSubUrl ?? '/' }));
|
: H.createBrowserHistory({ basename: config.appSubUrl ?? '/' }));
|
||||||
|
|
||||||
|
this.locationObservable = new BehaviorSubject(this.history.location);
|
||||||
|
|
||||||
|
this.history.listen((location) => {
|
||||||
|
this.locationObservable.next(location);
|
||||||
|
});
|
||||||
|
|
||||||
this.partial = this.partial.bind(this);
|
this.partial = this.partial.bind(this);
|
||||||
this.push = this.push.bind(this);
|
this.push = this.push.bind(this);
|
||||||
this.replace = this.replace.bind(this);
|
this.replace = this.replace.bind(this);
|
||||||
@ -48,6 +57,10 @@ export class HistoryWrapper implements LocationService {
|
|||||||
this.getLocation = this.getLocation.bind(this);
|
this.getLocation = this.getLocation.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLocationObservable() {
|
||||||
|
return this.locationObservable.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
getHistory() {
|
getHistory() {
|
||||||
return this.history;
|
return this.history;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
import { createContext, useContext } from 'react';
|
import { createContext, useContext } from 'react';
|
||||||
import { useObservable } from 'react-use';
|
import { useObservable } from 'react-use';
|
||||||
|
|
||||||
import { locationService as mainLocationService } from './LocationService';
|
|
||||||
import { SidecarService_EXPERIMENTAL, sidecarServiceSingleton_EXPERIMENTAL } from './SidecarService_EXPERIMENTAL';
|
import { SidecarService_EXPERIMENTAL, sidecarServiceSingleton_EXPERIMENTAL } from './SidecarService_EXPERIMENTAL';
|
||||||
|
|
||||||
export const SidecarContext_EXPERIMENTAL = createContext<SidecarService_EXPERIMENTAL>(
|
export const SidecarContext_EXPERIMENTAL = createContext<SidecarService_EXPERIMENTAL>(
|
||||||
sidecarServiceSingleton_EXPERIMENTAL
|
sidecarServiceSingleton_EXPERIMENTAL
|
||||||
);
|
);
|
||||||
|
|
||||||
const HIDDEN_ROUTES = ['/login'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main way to interact with the sidecar service inside a react context. It provides a wrapper around the
|
* This is the main way to interact with the sidecar service inside a react context. It provides a wrapper around the
|
||||||
* service props so that even though they are observables we just pass actual values to the components.
|
* service props so that even though they are observables we just pass actual values to the components.
|
||||||
@ -27,32 +24,25 @@ export function useSidecar_EXPERIMENTAL() {
|
|||||||
const initialContext = useObservable(service.initialContextObservable, service.initialContext);
|
const initialContext = useObservable(service.initialContextObservable, service.initialContext);
|
||||||
const activePluginId = useObservable(service.activePluginIdObservable, service.activePluginId);
|
const activePluginId = useObservable(service.activePluginIdObservable, service.activePluginId);
|
||||||
const locationService = service.getLocationService();
|
const locationService = service.getLocationService();
|
||||||
const forceHidden = HIDDEN_ROUTES.includes(mainLocationService.getLocation().pathname);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activePluginId: forceHidden ? undefined : activePluginId,
|
activePluginId,
|
||||||
initialContext: forceHidden ? undefined : initialContext,
|
initialContext,
|
||||||
locationService,
|
locationService,
|
||||||
// TODO: currently this allows anybody to open any app, in the future we should probably scope this to the
|
// TODO: currently this allows anybody to open any app, in the future we should probably scope this to the
|
||||||
// current app but that means we will need to incorporate this better into the plugin platform APIs which
|
// current app but that means we will need to incorporate this better into the plugin platform APIs which
|
||||||
// we will do once the functionality is reasonably stable
|
// we will do once the functionality is reasonably stable
|
||||||
openApp: (pluginId: string, context?: unknown) => {
|
openApp: (pluginId: string, context?: unknown) => {
|
||||||
if (forceHidden) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return service.openApp(pluginId, context);
|
return service.openApp(pluginId, context);
|
||||||
},
|
},
|
||||||
openAppV2: (pluginId: string, path?: string) => {
|
openAppV2: (pluginId: string, path?: string) => {
|
||||||
if (forceHidden) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return service.openAppV2(pluginId, path);
|
return service.openAppV2(pluginId, path);
|
||||||
},
|
},
|
||||||
|
openAppV3: (options: { pluginId: string; path?: string; follow?: boolean }) => {
|
||||||
|
return service.openAppV3(options);
|
||||||
|
},
|
||||||
closeApp: () => service.closeApp(),
|
closeApp: () => service.closeApp(),
|
||||||
isAppOpened: (pluginId: string) => {
|
isAppOpened: (pluginId: string) => {
|
||||||
if (forceHidden) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return service.isAppOpened(pluginId);
|
return service.isAppOpened(pluginId);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,28 @@
|
|||||||
|
import * as H from 'history';
|
||||||
|
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
|
|
||||||
|
import { HistoryWrapper } from './LocationService';
|
||||||
import { SidecarService_EXPERIMENTAL } from './SidecarService_EXPERIMENTAL';
|
import { SidecarService_EXPERIMENTAL } from './SidecarService_EXPERIMENTAL';
|
||||||
|
|
||||||
describe('SidecarService_EXPERIMENTAL', () => {
|
describe('SidecarService_EXPERIMENTAL', () => {
|
||||||
beforeEach(() => {
|
let mainLocationService: HistoryWrapper;
|
||||||
|
let sidecarService: SidecarService_EXPERIMENTAL;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
config.featureToggles.appSidecar = true;
|
config.featureToggles.appSidecar = true;
|
||||||
});
|
});
|
||||||
afterEach(() => {
|
|
||||||
config.featureToggles.appSidecar = undefined;
|
afterAll(() => {
|
||||||
|
config.featureToggles.appSidecar = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mainLocationService = new HistoryWrapper(H.createMemoryHistory({ initialEntries: ['/explore'] }));
|
||||||
|
sidecarService = new SidecarService_EXPERIMENTAL(mainLocationService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has the correct state after opening and closing an app', () => {
|
it('has the correct state after opening and closing an app', () => {
|
||||||
const sidecarService = new SidecarService_EXPERIMENTAL();
|
|
||||||
sidecarService.openApp('pluginId', { filter: 'test' });
|
sidecarService.openApp('pluginId', { filter: 'test' });
|
||||||
|
|
||||||
expect(sidecarService.activePluginId).toBe('pluginId');
|
expect(sidecarService.activePluginId).toBe('pluginId');
|
||||||
@ -25,7 +36,6 @@ describe('SidecarService_EXPERIMENTAL', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('has the correct state after opening and closing an app v2', () => {
|
it('has the correct state after opening and closing an app v2', () => {
|
||||||
const sidecarService = new SidecarService_EXPERIMENTAL();
|
|
||||||
sidecarService.openAppV2('pluginId', '/test');
|
sidecarService.openAppV2('pluginId', '/test');
|
||||||
|
|
||||||
expect(sidecarService.activePluginId).toBe('pluginId');
|
expect(sidecarService.activePluginId).toBe('pluginId');
|
||||||
@ -37,8 +47,19 @@ describe('SidecarService_EXPERIMENTAL', () => {
|
|||||||
expect(sidecarService.getLocationService().getLocation().pathname).toBe('/');
|
expect(sidecarService.getLocationService().getLocation().pathname).toBe('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('has the correct state after opening and closing an app v3', () => {
|
||||||
|
sidecarService.openAppV3({ pluginId: 'pluginId', path: '/test' });
|
||||||
|
|
||||||
|
expect(sidecarService.activePluginId).toBe('pluginId');
|
||||||
|
expect(sidecarService.getLocationService().getLocation().pathname).toBe('/a/pluginId/test');
|
||||||
|
|
||||||
|
sidecarService.closeApp();
|
||||||
|
expect(sidecarService.activePluginId).toBe(undefined);
|
||||||
|
expect(sidecarService.initialContext).toBe(undefined);
|
||||||
|
expect(sidecarService.getLocationService().getLocation().pathname).toBe('/');
|
||||||
|
});
|
||||||
|
|
||||||
it('reports correct opened state', () => {
|
it('reports correct opened state', () => {
|
||||||
const sidecarService = new SidecarService_EXPERIMENTAL();
|
|
||||||
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
|
||||||
sidecarService.openApp('pluginId');
|
sidecarService.openApp('pluginId');
|
||||||
@ -49,7 +70,6 @@ describe('SidecarService_EXPERIMENTAL', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('reports correct opened state v2', () => {
|
it('reports correct opened state v2', () => {
|
||||||
const sidecarService = new SidecarService_EXPERIMENTAL();
|
|
||||||
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
|
||||||
sidecarService.openAppV2('pluginId');
|
sidecarService.openAppV2('pluginId');
|
||||||
@ -58,4 +78,46 @@ describe('SidecarService_EXPERIMENTAL', () => {
|
|||||||
sidecarService.closeApp();
|
sidecarService.closeApp();
|
||||||
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('reports correct opened state v3', () => {
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
|
||||||
|
sidecarService.openAppV3({ pluginId: 'pluginId' });
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(true);
|
||||||
|
|
||||||
|
sidecarService.closeApp();
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('autocloses on not allowed routes', () => {
|
||||||
|
sidecarService.openAppV3({ pluginId: 'pluginId' });
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(true);
|
||||||
|
mainLocationService.push('/config');
|
||||||
|
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('autocloses on when changing route', () => {
|
||||||
|
sidecarService.openAppV3({ pluginId: 'pluginId' });
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(true);
|
||||||
|
mainLocationService.push('/a/other-app');
|
||||||
|
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not autocloses when set to follow', () => {
|
||||||
|
sidecarService.openAppV3({ pluginId: 'pluginId', follow: true });
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(true);
|
||||||
|
mainLocationService.push('/a/other-app');
|
||||||
|
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('autocloses on not allowed routes when set to follow', () => {
|
||||||
|
sidecarService.openAppV3({ pluginId: 'pluginId', follow: true });
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(true);
|
||||||
|
mainLocationService.push('/config');
|
||||||
|
|
||||||
|
expect(sidecarService.isAppOpened('pluginId')).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,17 @@ import { BehaviorSubject, map, Observable } from 'rxjs';
|
|||||||
import { reportInteraction } from '../analytics/utils';
|
import { reportInteraction } from '../analytics/utils';
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
|
|
||||||
import { HistoryWrapper, LocationService, locationService } from './LocationService';
|
import { HistoryWrapper, locationService as mainLocationService, LocationService } from './LocationService';
|
||||||
|
|
||||||
|
// Only allow sidecar to be opened on these routes. It does not seem to make sense to keep the sidecar opened on
|
||||||
|
// config/admin pages for example.
|
||||||
|
// At this moment let's be restrictive about where the sidecar can show and add more routes if there is a need.
|
||||||
|
const ALLOW_ROUTES = [
|
||||||
|
/(^\/d\/)/, // dashboards
|
||||||
|
/^\/explore/, // explore + explore metrics
|
||||||
|
/^\/a\/[^\/]+/, // app plugins
|
||||||
|
/^\/alerting/,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a service that handles state and operation of a sidecar feature (sideview to render a second app in grafana).
|
* This is a service that handles state and operation of a sidecar feature (sideview to render a second app in grafana).
|
||||||
@ -19,15 +29,26 @@ import { HistoryWrapper, LocationService, locationService } from './LocationServ
|
|||||||
*/
|
*/
|
||||||
export class SidecarService_EXPERIMENTAL {
|
export class SidecarService_EXPERIMENTAL {
|
||||||
private _initialContext: BehaviorSubject<unknown | undefined>;
|
private _initialContext: BehaviorSubject<unknown | undefined>;
|
||||||
private memoryLocationService: LocationService;
|
|
||||||
private history: LocationStorageHistory;
|
|
||||||
|
|
||||||
constructor() {
|
private sidecarLocationService: LocationService;
|
||||||
|
private mainLocationService: LocationService;
|
||||||
|
|
||||||
|
// If true we don't close the sidecar when user navigates to another app or part of Grafana from where the sidecar
|
||||||
|
// was opened.
|
||||||
|
private follow = false;
|
||||||
|
|
||||||
|
// Keep track of where the sidecar was originally opened for autoclose behaviour.
|
||||||
|
private mainLocationWhenOpened: string | undefined;
|
||||||
|
|
||||||
|
private mainOnAllowedRoute = false;
|
||||||
|
|
||||||
|
constructor(mainLocationService: LocationService) {
|
||||||
this._initialContext = new BehaviorSubject<unknown | undefined>(undefined);
|
this._initialContext = new BehaviorSubject<unknown | undefined>(undefined);
|
||||||
// We need a local ref for this so we can tap into the location changes and drive rerendering of components based
|
this.mainLocationService = mainLocationService;
|
||||||
// on it without having a parent Router.
|
this.sidecarLocationService = new HistoryWrapper(
|
||||||
this.history = createLocationStorageHistory({ storageKey: 'grafana.sidecar.history' });
|
createLocationStorageHistory({ storageKey: 'grafana.sidecar.history' })
|
||||||
this.memoryLocationService = new HistoryWrapper(this.history);
|
);
|
||||||
|
this.handleMainLocationChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private assertFeatureEnabled() {
|
private assertFeatureEnabled() {
|
||||||
@ -39,6 +60,48 @@ export class SidecarService_EXPERIMENTAL {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateMainLocationWhenOpened() {
|
||||||
|
const pathname = this.mainLocationService.getLocation().pathname;
|
||||||
|
for (const route of ALLOW_ROUTES) {
|
||||||
|
const match = pathname.match(route)?.[0];
|
||||||
|
if (match) {
|
||||||
|
this.mainLocationWhenOpened = match;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every time the main location changes we check if we should keep the sidecar open or close it based on list
|
||||||
|
* of allowed routes and also based on the follow flag when opening the app.
|
||||||
|
*/
|
||||||
|
private handleMainLocationChanges() {
|
||||||
|
this.mainOnAllowedRoute = ALLOW_ROUTES.some((prefix) =>
|
||||||
|
this.mainLocationService.getLocation().pathname.match(prefix)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.mainLocationService.getLocationObservable().subscribe((location) => {
|
||||||
|
if (!this.activePluginId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.mainOnAllowedRoute = ALLOW_ROUTES.some((prefix) => location.pathname.match(prefix));
|
||||||
|
|
||||||
|
if (!this.mainOnAllowedRoute) {
|
||||||
|
this.closeApp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We check if we moved to some other app or part of grafana from where we opened the sidecar.
|
||||||
|
const isTheSameLocation = Boolean(
|
||||||
|
this.mainLocationWhenOpened && location.pathname.startsWith(this.mainLocationWhenOpened)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!(isTheSameLocation || this.follow)) {
|
||||||
|
this.closeApp();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current app id of the app in sidecar. This is most probably provisional. In the future
|
* Get current app id of the app in sidecar. This is most probably provisional. In the future
|
||||||
* this should be driven by URL addressing so that routing for the apps don't change. Useful just internally
|
* this should be driven by URL addressing so that routing for the apps don't change. Useful just internally
|
||||||
@ -47,7 +110,7 @@ export class SidecarService_EXPERIMENTAL {
|
|||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
get activePluginIdObservable() {
|
get activePluginIdObservable() {
|
||||||
return this.history.getLocationObservable().pipe(
|
return this.sidecarLocationService.getLocationObservable().pipe(
|
||||||
map((val) => {
|
map((val) => {
|
||||||
return getPluginIdFromUrl(val?.pathname || '');
|
return getPluginIdFromUrl(val?.pathname || '');
|
||||||
})
|
})
|
||||||
@ -75,11 +138,11 @@ export class SidecarService_EXPERIMENTAL {
|
|||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
get activePluginId() {
|
get activePluginId() {
|
||||||
return getPluginIdFromUrl(this.memoryLocationService.getLocation().pathname);
|
return getPluginIdFromUrl(this.sidecarLocationService.getLocation().pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLocationService() {
|
getLocationService() {
|
||||||
return this.memoryLocationService;
|
return this.sidecarLocationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,26 +151,41 @@ export class SidecarService_EXPERIMENTAL {
|
|||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
openApp(pluginId: string, context?: unknown) {
|
openApp(pluginId: string, context?: unknown) {
|
||||||
if (!this.assertFeatureEnabled()) {
|
if (!(this.assertFeatureEnabled() && this.mainOnAllowedRoute)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._initialContext.next(context);
|
this._initialContext.next(context);
|
||||||
this.memoryLocationService.push({ pathname: `/a/${pluginId}` });
|
this.openAppV3({ pluginId, follow: false });
|
||||||
|
|
||||||
reportInteraction('sidecar_service_open_app', { pluginId, version: 1 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens an app in a sidecar. You can also relative path inside the app to open.
|
* Opens an app in a sidecar. You can also relative path inside the app to open.
|
||||||
|
* @deprecated
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
openAppV2(pluginId: string, path?: string) {
|
openAppV2(pluginId: string, path?: string) {
|
||||||
if (!this.assertFeatureEnabled()) {
|
this.openAppV3({ pluginId, path, follow: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens an app in a sidecar. You can also relative path inside the app to open.
|
||||||
|
* @param options.pluginId Plugin ID of the app to open
|
||||||
|
* @param options.path Relative path inside the app to open
|
||||||
|
* @param options.follow If true, the sidecar will stay open even if the main location change to another app or
|
||||||
|
* Grafana section
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
openAppV3(options: { pluginId: string; path?: string; follow?: boolean }) {
|
||||||
|
if (!(this.assertFeatureEnabled() && this.mainOnAllowedRoute)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.memoryLocationService.push({ pathname: `/a/${pluginId}${path || ''}` });
|
this.follow = options.follow || false;
|
||||||
reportInteraction('sidecar_service_open_app', { pluginId, version: 2 });
|
|
||||||
|
this.updateMainLocationWhenOpened();
|
||||||
|
this.sidecarLocationService.push({ pathname: `/a/${options.pluginId}${options.path || ''}` });
|
||||||
|
reportInteraction('sidecar_service_open_app', { pluginId: options.pluginId, follow: options.follow });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,8 +196,10 @@ export class SidecarService_EXPERIMENTAL {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.follow = false;
|
||||||
|
this.mainLocationWhenOpened = undefined;
|
||||||
this._initialContext.next(undefined);
|
this._initialContext.next(undefined);
|
||||||
this.memoryLocationService.replace({ pathname: '/' });
|
this.sidecarLocationService.replace({ pathname: '/' });
|
||||||
|
|
||||||
reportInteraction('sidecar_service_close_app');
|
reportInteraction('sidecar_service_close_app');
|
||||||
}
|
}
|
||||||
@ -160,7 +240,7 @@ function getPluginIdFromUrl(url: string) {
|
|||||||
function getMainAppPluginId() {
|
function getMainAppPluginId() {
|
||||||
// TODO: not great but we have to get a handle on the other locationService used for the main view and easiest way
|
// TODO: not great but we have to get a handle on the other locationService used for the main view and easiest way
|
||||||
// right now is through this global singleton
|
// right now is through this global singleton
|
||||||
const { pathname } = locationService.getLocation();
|
const { pathname } = mainLocationService.getLocation();
|
||||||
|
|
||||||
// A naive way to sort of simulate core features being an app and having an appID
|
// A naive way to sort of simulate core features being an app and having an appID
|
||||||
let mainApp = getPluginIdFromUrl(pathname);
|
let mainApp = getPluginIdFromUrl(pathname);
|
||||||
@ -258,4 +338,4 @@ function createLocationStorageHistory(options: LocalStorageHistoryOptions): Loca
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sidecarServiceSingleton_EXPERIMENTAL = new SidecarService_EXPERIMENTAL();
|
export const sidecarServiceSingleton_EXPERIMENTAL = new SidecarService_EXPERIMENTAL(mainLocationService);
|
||||||
|
Loading…
Reference in New Issue
Block a user