1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Convert all of kube-details-params/ and navigate/ to injectable

- This fixes a runtime error that was encountered during testing

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-04-22 11:10:36 -04:00
parent b3cf868078
commit fd86ea0d97
45 changed files with 576 additions and 262 deletions

View File

@ -134,7 +134,7 @@ export class KubernetesCluster<
}
}
class KubernetesClusterCategory extends CatalogCategory {
export class KubernetesClusterCategory extends CatalogCategory {
public readonly apiVersion = "catalog.k8slens.dev/v1alpha1";
public readonly kind = "CatalogCategory";
public metadata = {
@ -151,5 +151,3 @@ class KubernetesClusterCategory extends CatalogCategory {
},
};
}
export const kubernetesClusterCategory = new KubernetesClusterCategory();

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { GeneralCategory } from "../../catalog-entities";
import { builtInCategoryInjectionToken } from "../category-registry.injectable";
const generalCategoryInjectable = getInjectable({
id: "general-category",
instantiate: () => new GeneralCategory(),
injectionToken: builtInCategoryInjectionToken,
});
export default generalCategoryInjectable;

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { KubernetesClusterCategory } from "../../catalog-entities/kubernetes-cluster";
import { builtInCategoryInjectionToken } from "../category-registry.injectable";
const kubernetesClusterCategoryInjectable = getInjectable({
id: "kubernetes-cluster-category",
instantiate: () => new KubernetesClusterCategory(),
injectionToken: builtInCategoryInjectionToken,
});
export default kubernetesClusterCategoryInjectable;

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { WebLinkCategory } from "../../catalog-entities";
import { builtInCategoryInjectionToken } from "../category-registry.injectable";
const weblinkCategoryInjectable = getInjectable({
id: "weblink-category",
instantiate: () => new WebLinkCategory(),
injectionToken: builtInCategoryInjectionToken,
});
export default weblinkCategoryInjectable;

View File

@ -2,18 +2,25 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { GeneralCategory, kubernetesClusterCategory, WebLinkCategory } from "../catalog-entities";
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
import { WebLinkCategory } from "../catalog-entities";
import type { CatalogCategory } from "./catalog-entity";
import { CatalogCategoryRegistry } from "./category-registry";
export const builtInCategoryInjectionToken = getInjectionToken<CatalogCategory>({
id: "built-in-category-token",
});
const catalogCategoryRegistryInjectable = getInjectable({
id: "catalog-category-registry",
instantiate: () => {
instantiate: (di) => {
const registry = new CatalogCategoryRegistry();
const categories = di.injectMany(builtInCategoryInjectionToken);
for (const category of categories) {
registry.add(category);
}
// TODO: move to different place
registry.add(new GeneralCategory());
registry.add(kubernetesClusterCategory);
registry.add(new WebLinkCategory());
return registry;

View File

@ -3,13 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import kubernetesClusterCategoryInjectable from "../../common/catalog/categories/kubernetes-cluster.injectable";
import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
export {
KubernetesCluster,
kubernetesClusterCategory,
GeneralEntity,
WebLink,
} from "../../common/catalog-entities";
export const kubernetesClusterCategory = asLegacyGlobalForExtensionApi(kubernetesClusterCategoryInjectable);
export type {
KubernetesClusterPrometheusMetrics,
KubernetesClusterSpec,

View File

@ -40,6 +40,6 @@ export interface RegisteredPage {
id: string;
extensionId: string;
url: string; // registered extension's page URL (without page params)
params: PageParams<PageParam>; // normalized params
params: PageParams<PageParam<any>>; // normalized params
components: PageComponents; // normalized components
}

View File

@ -3,14 +3,20 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { PageParamInit } from "../../renderer/navigation";
import { navigation, PageParam } from "../../renderer/navigation";
import getDetailsUrlInjectable from "../../renderer/components/kube-detail-params/get-details-url.injectable";
import hideDetailsInjectable from "../../renderer/components/kube-detail-params/hide-details.injectable";
import showDetailsInjectable from "../../renderer/components/kube-detail-params/show-details.injectable";
import createPageParamInjectable from "../../renderer/navigation/create-page-param.injectable";
import isActiveRouteInjectable from "../../renderer/navigation/is-route-active.injectable";
import navigateInjectable from "../../renderer/navigation/navigate.injectable";
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
export type { PageParamInit, PageParam } from "../../renderer/navigation/page-param";
export { navigate, isActiveRoute } from "../../renderer/navigation/helpers";
export { hideDetails, showDetails, getDetailsUrl } from "../../renderer/components/kube-detail-params";
export type { PageParamInit, PageParam } from "../../renderer/navigation";
export type { URLParams } from "../../common/utils/buildUrl";
export function createPageParam<V>(init: PageParamInit<V>) {
return new PageParam<V>(init, navigation);
}
export const getDetailsUrl = asLegacyGlobalFunctionForExtensionApi(getDetailsUrlInjectable);
export const showDetails = asLegacyGlobalFunctionForExtensionApi(showDetailsInjectable);
export const hideDetails = asLegacyGlobalFunctionForExtensionApi(hideDetailsInjectable);
export const createPageParam = asLegacyGlobalFunctionForExtensionApi(createPageParamInjectable);
export const isActiveRoute = asLegacyGlobalFunctionForExtensionApi(isActiveRouteInjectable);
export const navigate = asLegacyGlobalFunctionForExtensionApi(navigateInjectable);

View File

@ -1,24 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { when } from "mobx";
import { catalogCategoryRegistry } from "../../../common/catalog";
import { catalogEntityRegistry } from "../catalog-entity-registry";
import { isActiveRoute } from "../../navigation";
import assert from "assert";
export async function setEntityOnRouteMatch() {
await when(() => catalogEntityRegistry.entities.size > 0);
const generalCategory = catalogCategoryRegistry.getByName("General");
assert(generalCategory);
const entities = catalogEntityRegistry.getItemsForCategory(generalCategory);
const activeEntity = entities.find(entity => isActiveRoute(entity.spec.path));
if (activeEntity) {
catalogEntityRegistry.activeEntity = activeEntity;
}
}

View File

@ -0,0 +1,52 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { reaction, when } from "mobx";
import generalCategoryInjectable from "../../../common/catalog/categories/general.injectable";
import isActiveRouteInjectable from "../../navigation/is-route-active.injectable";
import observableHistoryInjectable from "../../navigation/observable-history.injectable";
import type { Disposer } from "../../utils";
import { disposer } from "../../utils";
import catalogEntityRegistryInjectable from "../catalog-entity-registry/catalog-entity-registry.injectable";
export type WatchForGeneralEntityNavigation = () => Disposer;
const watchForGeneralEntityNavigationInjectable = getInjectable({
id: "watch-for-general-entity-navigation",
instantiate: (di): WatchForGeneralEntityNavigation => {
const observableHistory = di.inject(observableHistoryInjectable);
const isActiveRoute = di.inject(isActiveRouteInjectable);
const entityRegistry = di.inject(catalogEntityRegistryInjectable);
const generalCategory = di.inject(generalCategoryInjectable);
return () => {
const dispose = disposer();
dispose.push(when(
() => entityRegistry.entities.size > 0,
() => {
dispose.push(reaction(
() => observableHistory.location,
() => {
const entities = entityRegistry.getItemsForCategory(generalCategory);
const activeEntity = entities.find(entity => isActiveRoute(entity.spec.path));
if (activeEntity) {
entityRegistry.activeEntity = activeEntity;
}
},
{
fireImmediately: true,
},
));
},
));
return dispose;
};
},
});
export default watchForGeneralEntityNavigationInjectable;

View File

@ -45,6 +45,7 @@ import { bindEvents } from "./navigation/events";
import assert from "assert";
import openDeleteClusterDialogInjectable from "./components/delete-cluster-dialog/open.injectable";
import { init } from "@sentry/electron/renderer";
import kubernetesClusterCategoryInjectable from "../common/catalog/categories/kubernetes-cluster.injectable";
configurePackages(); // global packages
registerCustomThemes(); // monaco editor themes
@ -95,13 +96,11 @@ export async function bootstrap(di: DiContainer) {
logger.info(`${logPrefix} initializing CatalogEntityDetailRegistry`);
initializers.initCatalogEntityDetailRegistry();
const navigateToAddCluster = di.inject(navigateToAddClusterInjectable);
const addSyncEntries = di.inject(addSyncEntriesInjectable);
logger.info(`${logPrefix} initializing CatalogCategoryRegistryEntries`);
initializers.initCatalogCategoryRegistryEntries({
navigateToAddCluster,
addSyncEntries,
navigateToAddCluster: di.inject(navigateToAddClusterInjectable),
addSyncEntries: di.inject(addSyncEntriesInjectable),
kubernetesClusterCategory: di.inject(kubernetesClusterCategoryInjectable),
});
logger.info(`${logPrefix} initializing Catalog`);

View File

@ -15,7 +15,6 @@ import { cssNames, prevDefault } from "../../utils";
import type { ItemObject } from "../../../common/item.store";
import { Spinner } from "../spinner";
import type { ThemeStore } from "../../themes/store";
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
import type { ApiManager } from "../../../common/k8s-api/api-manager";
import { KubeObjectAge } from "../kube-object/age";
import { withInjectables } from "@ogre-tools/injectable-react";
@ -25,6 +24,10 @@ import type { EventStore } from "../+events/store";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import eventStoreInjectable from "../+events/store.injectable";
import nodeStoreInjectable from "../+nodes/store.injectable";
import type { PageParam } from "../../navigation";
import type { ToggleDetails } from "../kube-detail-params/toggle-details.injectable";
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
import toggleDetailsInjectable from "../kube-detail-params/toggle-details.injectable";
export interface ClusterIssuesProps {
className?: string;
@ -49,6 +52,8 @@ interface Dependencies {
nodeStore: NodeStore;
eventStore: EventStore;
apiManager: ApiManager;
kubeSelectedUrlParam: PageParam<string>;
toggleDetails: ToggleDetails;
}
@observer
@ -86,6 +91,7 @@ class NonInjectedClusterIssues extends React.Component<ClusterIssuesProps & Depe
getTableRow = (uid: string) => {
const { warnings } = this;
const { kubeSelectedUrlParam, toggleDetails } = this.props;
const warning = warnings.find(warn => warn.getId() == uid);
if (!warning) {
@ -189,5 +195,7 @@ export const ClusterIssues = withInjectables<Dependencies, ClusterIssuesProps>(N
apiManager: di.inject(apiManagerInjectable),
eventStore: di.inject(eventStoreInjectable),
nodeStore: di.inject(nodeStoreInjectable),
kubeSelectedUrlParam: di.inject(kubeSelectedUrlParamInjectable),
toggleDetails: di.inject(toggleDetailsInjectable),
}),
});

View File

@ -14,13 +14,11 @@ const closePreferencesInjectable = getInjectable({
const navigateToFrontPage = di.inject(navigateToFrontPageInjectable);
return () => {
if (observableHistory.length === 1) {
if (observableHistory.length <= 1) {
navigateToFrontPage();
return;
} else {
observableHistory.goBack();
}
observableHistory.goBack();
};
},
});

View File

@ -15,25 +15,25 @@ import { withInjectables } from "@ogre-tools/injectable-react";
import { TopBar } from "../layout/top-bar/top-bar";
import catalogPreviousActiveTabStorageInjectable from "../+catalog/catalog-previous-active-tab-storage/catalog-previous-active-tab-storage.injectable";
import type { IComputedValue } from "mobx";
import { reaction } from "mobx";
import currentRouteComponentInjectable from "../../routes/current-route-component.injectable";
import { setEntityOnRouteMatch } from "../../api/helpers/general-active-sync";
import { navigation } from "../../navigation";
import welcomeRouteInjectable from "../../../common/front-end-routing/routes/welcome/welcome-route.injectable";
import { buildURL } from "../../../common/utils/buildUrl";
import type { StorageLayer } from "../../utils";
import type { WatchForGeneralEntityNavigation } from "../../api/helpers/watch-for-general-entity-navigation.injectable";
import watchForGeneralEntityNavigationInjectable from "../../api/helpers/watch-for-general-entity-navigation.injectable";
interface Dependencies {
catalogPreviousActiveTabStorage: StorageLayer<string | null>;
currentRouteComponent: IComputedValue<React.ElementType | undefined>;
welcomeUrl: string;
watchForGeneralEntityNavigation: WatchForGeneralEntityNavigation;
}
@observer
class NonInjectedClusterManager extends React.Component<Dependencies> {
componentDidMount() {
disposeOnUnmount(this, [
reaction(() => navigation.location, () => setEntityOnRouteMatch(), { fireImmediately: true }),
this.props.watchForGeneralEntityNavigation(),
]);
}
@ -64,5 +64,6 @@ export const ClusterManager = withInjectables<Dependencies>(NonInjectedClusterMa
catalogPreviousActiveTabStorage: di.inject(catalogPreviousActiveTabStorageInjectable),
currentRouteComponent: di.inject(currentRouteComponentInjectable),
welcomeUrl: buildURL(di.inject(welcomeRouteInjectable).path),
watchForGeneralEntityNavigation: di.inject(watchForGeneralEntityNavigationInjectable),
}),
});

View File

@ -18,7 +18,7 @@ import drawerStorageInjectable, {
defaultDrawerWidth,
} from "./drawer-storage/drawer-storage.injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import historyInjectable from "../../navigation/history/history.injectable";
import historyInjectable from "../../navigation/history.injectable";
import type { History } from "history";
export type DrawerPosition = "top" | "left" | "right" | "bottom";

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import observableHistoryInjectable from "../../navigation/observable-history.injectable";
import kubeDetailsUrlParamInjectable from "./kube-details-url.injectable";
import kubeSelectedUrlParamInjectable from "./kube-selected-url.injectable";
export type GetDetailsUrl = (selfLink: string, resetSelected?: boolean, mergeGlobals?: boolean) => string;
const getDetailsUrlInjectable = getInjectable({
id: "get-details-url",
instantiate: (di): GetDetailsUrl => {
const observableHistory = di.inject(observableHistoryInjectable);
const kubeDetailsUrlParam = di.inject(kubeDetailsUrlParamInjectable);
const kubeSelectedUrlParam = di.inject(kubeSelectedUrlParamInjectable);
return (selfLink, resetSelected = false, mergeGlobals = true) => {
const params = new URLSearchParams(mergeGlobals ? observableHistory.searchParams : "");
params.set(kubeDetailsUrlParam.name, selfLink);
if (resetSelected) {
params.delete(kubeSelectedUrlParam.name);
} else {
params.set(kubeSelectedUrlParam.name, kubeSelectedUrlParam.get());
}
return `?${params}`;
};
},
});
export default getDetailsUrlInjectable;

View File

@ -2,12 +2,18 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { hideDetails } from "../../kube-detail-params";
import { getInjectable } from "@ogre-tools/injectable";
import showDetailsInjectable from "./show-details.injectable";
export type HideDetails = () => void;
const hideDetailsInjectable = getInjectable({
id: "hide-details",
instantiate: () => hideDetails,
instantiate: (di): HideDetails => {
const showDetails = di.inject(showDetailsInjectable);
return () => showDetails("");
},
});
export default hideDetailsInjectable;

View File

@ -3,4 +3,16 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export * from "./params";
import { asLegacyGlobalFunctionForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import getDetailsUrlInjectable from "./get-details-url.injectable";
import showDetailsInjectable from "./show-details.injectable";
/**
* @deprecated use `di.inject(getDetailsUrlInjectable)` instead
*/
export const getDetailsUrl = asLegacyGlobalFunctionForExtensionApi(getDetailsUrlInjectable);
/**
* @deprecated use `di.inject(showDetailsInjectable)` instead
*/
export const showDetails = asLegacyGlobalFunctionForExtensionApi(showDetailsInjectable);

View File

@ -0,0 +1,22 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import createPageParamInjectable from "../../navigation/create-page-param.injectable";
/**
* Used to store `object.selfLink` to show more info about resource in the details panel.
*/
const kubeDetailsUrlParamInjectable = getInjectable({
id: "kube-details-url-param",
instantiate: (di) => {
const createPageParam = di.inject(createPageParamInjectable);
return createPageParam({
name: "kube-details",
});
},
});
export default kubeDetailsUrlParamInjectable;

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import createPageParamInjectable from "../../navigation/create-page-param.injectable";
import kubeDetailsUrlParamInjectable from "./kube-details-url.injectable";
/**
* Used to highlight last active/selected table row with the resource.
*
* @example
* If we go to "Nodes (page) -> Node (details) -> Pod (details)",
* last clicked Node should be "active" while Pod details are shown).
*/
const kubeSelectedUrlParamInjectable = getInjectable({
id: "kube-selected-url-param",
instantiate: (di) => {
const createPageParam = di.inject(createPageParamInjectable);
const kubeDetailsUrlParam = di.inject(kubeDetailsUrlParamInjectable);
return createPageParam({
name: "kube-selected",
get defaultValue() {
return kubeDetailsUrlParam.get();
},
});
},
});
export default kubeSelectedUrlParamInjectable;

View File

@ -1,60 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { createPageParam, navigation } from "../../navigation";
/**
* Used to store `object.selfLink` to show more info about resource in the details panel.
*/
export const kubeDetailsUrlParam = createPageParam({
name: "kube-details",
});
/**
* Used to highlight last active/selected table row with the resource.
*
* @example
* If we go to "Nodes (page) -> Node (details) -> Pod (details)",
* last clicked Node should be "active" while Pod details are shown).
*/
export const kubeSelectedUrlParam = createPageParam({
name: "kube-selected",
get defaultValue() {
return kubeDetailsUrlParam.get();
},
});
export function toggleDetails(selfLink: string | undefined, resetSelected = true) {
const current = kubeSelectedUrlParam.get() === selfLink;
if (current) {
hideDetails();
} else {
showDetails(selfLink, resetSelected);
}
}
export function showDetails(selfLink = "", resetSelected = true) {
const detailsUrl = getDetailsUrl(selfLink, resetSelected);
navigation.merge({ search: detailsUrl });
}
export function hideDetails() {
showDetails();
}
export function getDetailsUrl(selfLink: string, resetSelected = false, mergeGlobals = true) {
const params = new URLSearchParams(mergeGlobals ? navigation.searchParams : "");
params.set(kubeDetailsUrlParam.name, selfLink);
if (resetSelected) {
params.delete(kubeSelectedUrlParam.name);
} else {
params.set(kubeSelectedUrlParam.name, kubeSelectedUrlParam.get());
}
return `?${params}`;
}

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import observableHistoryInjectable from "../../navigation/observable-history.injectable";
import getDetailsUrlInjectable from "./get-details-url.injectable";
/**
* @param selfLink The Kube selflink to show details for
* @param resetSelected If true then will reset the selected kube object (which object is highlighted generally)
* @default resetSelected true
*/
export type ShowDetails = (selfLink: string, resetSelected?: boolean) => void;
const showDetailsInjectable = getInjectable({
id: "show-details",
instantiate: (di): ShowDetails => {
const observableHistory = di.inject(observableHistoryInjectable);
const getDetailsUrl = di.inject(getDetailsUrlInjectable);
return (selfLink, resetSelected = true) => {
observableHistory.merge({
search: getDetailsUrl(selfLink, resetSelected),
});
};
},
});
export default showDetailsInjectable;

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import hideDetailsInjectable from "./hide-details.injectable";
import kubeSelectedUrlParamInjectable from "./kube-selected-url.injectable";
import showDetailsInjectable from "./show-details.injectable";
export interface ToggleDetails {
/**
* @param selfLink The selfLink of the kube object to toggle the details panal of
* @param resetSelected If true then the selected kube object (for the current list view) will be reset
* @default resetSelected true
*/
(selfLink: string, resetSelected?: boolean): void;
/**
* @deprecated Future versions will not support passing in `selfLink` that is `undefined`
*/
(selfLink: string | undefined, resetSelected?: boolean): void;
}
const toggleDetailsInjectable = getInjectable({
id: "toggle-details",
instantiate: (di): ToggleDetails => {
const showDetails = di.inject(showDetailsInjectable);
const hideDetails = di.inject(hideDetailsInjectable);
const kubeSelectedUrlParam = di.inject(kubeSelectedUrlParamInjectable);
return (selfLink, resetSelected = true) => {
const current = kubeSelectedUrlParam.get() === selfLink;
if (current || !selfLink) {
hideDetails();
} else {
showDetails(selfLink, resetSelected);
}
};
},
});
export default toggleDetailsInjectable;

View File

@ -11,37 +11,50 @@ import { computed, observable, reaction, makeObservable } from "mobx";
import { Drawer } from "../drawer";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { Spinner } from "../spinner";
import { apiManager } from "../../../common/k8s-api/api-manager";
import { customResourceDefinitionStore } from "../+custom-resources/legacy-store";
import type { ApiManager } from "../../../common/k8s-api/api-manager";
import { KubeObjectMenu } from "../kube-object-menu";
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { CustomResourceDetails } from "../+custom-resources";
import { KubeObjectMeta } from "../kube-object-meta";
import { hideDetails, kubeDetailsUrlParam } from "../kube-detail-params";
import type { PageParam } from "../../navigation";
import type { HideDetails } from "../kube-detail-params/hide-details.injectable";
import type { CustomResourceDefinitionStore } from "../+custom-resources/definition.store";
import { withInjectables } from "@ogre-tools/injectable-react";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import customResourceDefinitionStoreInjectable from "../+custom-resources/definition.store.injectable";
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
import kubeDetailsUrlParamInjectable from "../kube-detail-params/kube-details-url.injectable";
export interface KubeObjectDetailsProps<T extends KubeObject = KubeObject> {
export interface KubeObjectDetailsProps<Kube extends KubeObject = KubeObject> {
className?: string;
object: T;
object: Kube;
}
interface Dependencies {
kubeDetailsUrlParam: PageParam<string>;
apiManager: ApiManager;
hideDetails: HideDetails;
customResourceDefinitionStore: CustomResourceDefinitionStore;
}
@observer
export class KubeObjectDetails extends React.Component {
class NonInjectedKubeObjectDetails extends React.Component<Dependencies> {
@observable isLoading = false;
@observable.ref loadingError: React.ReactNode;
constructor(props: {}) {
constructor(props: Dependencies) {
super(props);
makeObservable(this);
}
@computed get path() {
return kubeDetailsUrlParam.get();
return this.props.kubeDetailsUrlParam.get();
}
@computed get object() {
try {
return apiManager
return this.props.apiManager
.getStore(this.path)
?.getByPath(this.path);
} catch (error) {
@ -56,13 +69,13 @@ export class KubeObjectDetails extends React.Component {
reaction(() => [
this.path,
this.object, // resource might be updated via watch-event or from already opened details
customResourceDefinitionStore.items.length, // crd stores initialized after loading
this.props.customResourceDefinitionStore.items.length, // crd stores initialized after loading
], async () => {
this.loadingError = "";
const { path, object } = this;
if (!object) {
const store = apiManager.getStore(path);
const store = this.props.apiManager.getStore(path);
if (store) {
this.isLoading = true;
@ -103,7 +116,7 @@ export class KubeObjectDetails extends React.Component {
));
if (details.length === 0) {
const crd = customResourceDefinitionStore.getByObject(object);
const crd = this.props.customResourceDefinitionStore.getByObject(object);
/**
* This is a fallback so that if a custom resource object doesn't have
@ -141,10 +154,20 @@ export class KubeObjectDetails extends React.Component {
open={!!(object || isLoading || loadingError)}
title={this.renderTitle(object)}
toolbar={object && <KubeObjectMenu object={object} toolbar={true}/>}
onClose={hideDetails}
onClose={this.props.hideDetails}
>
{object && this.renderContents(object)}
</Drawer>
);
}
}
export const KubeObjectDetails = withInjectables<Dependencies>(NonInjectedKubeObjectDetails, {
getProps: (di, props) => ({
...props,
apiManager: di.inject(apiManagerInjectable),
customResourceDefinitionStore: di.inject(customResourceDefinitionStoreInjectable),
hideDetails: di.inject(hideDetailsInjectable),
kubeDetailsUrlParam: di.inject(kubeDetailsUrlParamInjectable),
}),
});

View File

@ -17,7 +17,6 @@ import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"
import { KubeObjectMenu } from "../kube-object-menu";
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
import { ResourceKindMap, ResourceNames } from "../../utils/rbac";
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
import { Icon } from "../icon";
import { TooltipPosition } from "../tooltip";
import { withInjectables } from "@ogre-tools/injectable-react";
@ -26,6 +25,10 @@ import clusterFrameContextInjectable from "../../cluster-frame-context/cluster-f
import type { SubscribableStore, SubscribeStores } from "../../kube-watch-api/kube-watch-api";
import type { KubeApi } from "../../../common/k8s-api/kube-api";
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
import type { PageParam } from "../../navigation";
import type { ToggleDetails } from "../kube-detail-params/toggle-details.injectable";
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
import toggleDetailsInjectable from "../kube-detail-params/toggle-details.injectable";
export interface KubeObjectListLayoutProps<
K extends KubeObject,
@ -42,6 +45,8 @@ export interface KubeObjectListLayoutProps<
interface Dependencies {
clusterFrameContext: ClusterFrameContext;
subscribeToStores: SubscribeStores;
kubeSelectedUrlParam: PageParam<string>;
toggleDetails: ToggleDetails;
}
@observer
@ -51,14 +56,13 @@ class NonInjectedKubeObjectListLayout<
D extends KubeJsonApiDataFor<K>,
> extends React.Component<KubeObjectListLayoutProps<K, A, D> & Dependencies> {
static defaultProps = {
onDetails: (item: KubeObject) => toggleDetails(item.selfLink),
subscribeStores: true,
};
private loadErrors = observable.array<string>();
@computed get selectedItem() {
return this.props.store.getByPath(kubeSelectedUrlParam.get());
return this.props.store.getByPath(this.props.kubeSelectedUrlParam.get());
}
componentDidMount() {
@ -104,7 +108,16 @@ class NonInjectedKubeObjectListLayout<
}
render() {
const { className, customizeHeader, store, items, dependentStores, ...layoutProps } = this.props;
const {
className,
customizeHeader,
store,
items,
dependentStores,
toggleDetails,
onDetails,
...layoutProps
} = this.props;
const placeholderString = ResourceNames[ResourceKindMap[store.api.kind]] || store.api.kind;
return (
@ -137,13 +150,14 @@ class NonInjectedKubeObjectListLayout<
...[customizeHeader].filter(isDefined).flat(),
]}
renderItemMenu={item => <KubeObjectMenu object={item} />}
onDetails={onDetails ?? ((item) => toggleDetails(item.selfLink))}
{...layoutProps}
/>
);
}
}
const InjectedKubeObjectListLayout = withInjectables<
export const KubeObjectListLayout = withInjectables<
Dependencies,
KubeObjectListLayoutProps<KubeObject, KubeApi<KubeObject, KubeJsonApiDataFor<KubeObject>>, KubeJsonApiDataFor<KubeObject>>
>(NonInjectedKubeObjectListLayout, {
@ -151,13 +165,11 @@ const InjectedKubeObjectListLayout = withInjectables<
...props,
clusterFrameContext: di.inject(clusterFrameContextInjectable),
subscribeToStores: di.inject(subscribeStoresInjectable),
kubeSelectedUrlParam: di.inject(kubeSelectedUrlParamInjectable),
toggleDetails: di.inject(toggleDetailsInjectable),
}),
});
export function KubeObjectListLayout<
}) as <
K extends KubeObject,
A extends KubeApi<K, D>,
D extends KubeJsonApiDataFor<K> = KubeJsonApiDataFor<K>,
>(props: KubeObjectListLayoutProps<K, A, D>) {
return <InjectedKubeObjectListLayout {...(props as never)} />;
}
>(props: KubeObjectListLayoutProps<K, A, D>) => React.ReactElement;

View File

@ -13,9 +13,10 @@ import type { ApiManager } from "../../../common/k8s-api/api-manager";
import { withInjectables } from "@ogre-tools/injectable-react";
import clusterNameInjectable from "./dependencies/cluster-name.injectable";
import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable";
import hideDetailsInjectable from "./dependencies/hide-details.injectable";
import kubeObjectMenuItemsInjectable from "./dependencies/kube-object-menu-items/kube-object-menu-items.injectable";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import type { HideDetails } from "../kube-detail-params/hide-details.injectable";
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
export interface KubeObjectMenuProps<TKubeObject extends KubeObject> extends MenuActionsProps {
object: TKubeObject;
@ -27,7 +28,7 @@ interface Dependencies {
apiManager: ApiManager;
kubeObjectMenuItems: React.ElementType[];
clusterName: string | undefined;
hideDetails: () => void;
hideDetails: HideDetails;
createEditResourceTab: (kubeObject: KubeObject) => void;
}

View File

@ -12,7 +12,7 @@ import { cssNames } from "../../utils";
import { CloseButton } from "./close-button";
import { getLegacyGlobalDiForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
import observableHistoryInjectable from "../../navigation/history/observable.injectable";
import observableHistoryInjectable from "../../navigation/observable-history.injectable";
export interface SettingLayoutProps extends React.DOMAttributes<any> {
className?: IClassName;

View File

@ -37,7 +37,7 @@ import { observable, toJS } from "mobx";
import type { Draft } from "immer";
import { produce, isDraft } from "immer";
import type { GetDiForUnitTestingOptions } from "../test-utils/get-dis-for-unit-testing";
import historyInjectable from "./navigation/history/history.injectable";
import historyInjectable from "./navigation/history.injectable";
export interface GetRendererDiForUnitTestingOptions extends GetDiForUnitTestingOptions {
overrideCreateStorage?: boolean;

View File

@ -3,16 +3,21 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { kubernetesClusterCategory } from "../../common/catalog-entities";
import type { KubernetesClusterCategory } from "../../common/catalog-entities";
import { isLinux, isWindows } from "../../common/vars";
import { PathPicker } from "../components/path-picker";
interface Dependencies {
navigateToAddCluster: () => void;
addSyncEntries: (filePaths: string[]) => void;
kubernetesClusterCategory: KubernetesClusterCategory;
}
export function initCatalogCategoryRegistryEntries({ navigateToAddCluster, addSyncEntries } : Dependencies) {
export function initCatalogCategoryRegistryEntries({
navigateToAddCluster,
addSyncEntries,
kubernetesClusterCategory,
} : Dependencies) {
kubernetesClusterCategory.on("catalogAddMenu", ctx => {
ctx.menuItems.push(
{

View File

@ -0,0 +1,23 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import observableHistoryInjectable from "./observable-history.injectable";
import type { PageParamDependencies, PageParamInit } from "./page-param";
import { PageParam } from "./page-param";
export type CreatePageParam = <Value = string>(init: PageParamInit<Value>) => PageParam<Value>;
const createPageParamInjectable = getInjectable({
id: "create-page-param",
instantiate: (di): CreatePageParam => {
const deps: PageParamDependencies = {
history: di.inject(observableHistoryInjectable),
};
return (init) => new PageParam(deps, init);
},
});
export default createPageParamInjectable;

View File

@ -1,36 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { LocationDescriptor } from "history";
import { createPath } from "history";
import type { RouteProps } from "react-router";
import { matchPath } from "react-router";
import { navigation } from "./history";
import type { PageParamInit } from "./page-param";
import { PageParam } from "./page-param";
export function navigate(location: LocationDescriptor) {
const currentLocation = createPath(navigation.location);
navigation.push(location);
const newLocation = createPath(navigation.location);
if (currentLocation === newLocation) {
navigation.goBack(); // prevent sequences of same url in history
}
}
export function createPageParam<V = string>(init: PageParamInit<V>) {
return new PageParam<V>(init, navigation);
}
export function matchRoute<P>(route: string | string[] | RouteProps) {
return matchPath<P>(navigation.location.pathname, route);
}
export function isActiveRoute(route: string | string[] | RouteProps): boolean {
return !!matchRoute(route);
}

View File

@ -1,14 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import observableHistoryInjectable from "./history/observable.injectable";
export { searchParamsOptions } from "./history/search-params";
/**
* @deprecated: Switch to using di.inject(observableHistoryInjectable)
*/
export const navigation = asLegacyGlobalForExtensionApi(observableHistoryInjectable);

View File

@ -3,8 +3,33 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
// Navigation (renderer)
import { asLegacyGlobalFunctionForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import createPageParamInjectable from "./create-page-param.injectable";
import matchRouteInjectable from "./match-route.injectable";
import navigateInjectable from "./navigate.injectable";
import observableHistoryInjectable from "./observable-history.injectable";
export { searchParamsOptions } from "./search-params";
/**
* @deprecated use `di.inject(observableHistoryInjectable)` instead
*/
export const navigation = asLegacyGlobalForExtensionApi(observableHistoryInjectable);
/**
* @deprecated use `di.inject(navigateInjectable)` instead
*/
export const navigate = asLegacyGlobalFunctionForExtensionApi(navigateInjectable);
/**
* @deprecated use `di.inject(createPageParamInjectable)` instead
*/
export const createPageParam = asLegacyGlobalFunctionForExtensionApi(createPageParamInjectable);
/**
* @deprecated use `di.inject(matchRouteInjectable)` instead
*/
export const matchRoute = asLegacyGlobalFunctionForExtensionApi(matchRouteInjectable);
export * from "./history";
export * from "./helpers";
export * from "./page-param";

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { RouteProps } from "react-router";
import matchRouteInjectable from "./match-route.injectable";
export type IsRouteActive = (route: string | string[] | RouteProps) => boolean;
const isActiveRouteInjectable = getInjectable({
id: "is-active-route",
instantiate: (di): IsRouteActive => {
const matchRoute = di.inject(matchRouteInjectable);
return (route) => Boolean(matchRoute(route));
},
});
export default isActiveRouteInjectable;

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { match, RouteProps } from "react-router";
import { matchPath } from "react-router";
import observableHistoryInjectable from "./observable-history.injectable";
export type MatchRoute = <Params>(route: string | string[] | RouteProps) => match<Params> | null;
const matchRouteInjectable = getInjectable({
id: "match-route",
instantiate: (di): MatchRoute => {
const observableHistory = di.inject(observableHistoryInjectable);
return (route) => matchPath(observableHistory.location.pathname, route);
},
});
export default matchRouteInjectable;

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { LocationDescriptor } from "history";
import { action } from "mobx";
import observableHistoryInjectable from "./observable-history.injectable";
import { createPath } from "history";
export type Navigate = (location: LocationDescriptor) => void;
const navigateInjectable = getInjectable({
id: "navigate",
instantiate: (di): Navigate => {
const observableHistory = di.inject(observableHistoryInjectable);
return action((location) => {
const currentLocation = createPath(observableHistory.location);
observableHistory.push(location);
const newLocation = createPath(observableHistory.location);
if (currentLocation === newLocation) {
observableHistory.goBack(); // prevent sequences of same url in history
}
});
},
});
export default navigateInjectable;

View File

@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { createObservableHistory } from "mobx-observable-history";
import loggerInjectable from "../../../common/logger.injectable";
import loggerInjectable from "../../common/logger.injectable";
import { searchParamsOptions } from "./search-params";
import historyInjectable from "./history.injectable";

View File

@ -7,19 +7,23 @@
import { action, makeObservable } from "mobx";
import type { ObservableHistory } from "mobx-observable-history";
export interface PageParamInit<V = any> {
export interface PageParamInit<Value = any> {
name: string;
defaultValue?: V; // multi-values param must be defined with array-value, e.g. []
parse?(value: string | string[]): V; // from URL
stringify?(value: V): string | string[]; // to URL
defaultValue?: Value; // multi-values param must be defined with array-value, e.g. []
parse?(value: string | string[]): Value; // from URL
stringify?(value: Value): string | string[]; // to URL
}
export interface PageParamDependencies {
readonly history: ObservableHistory<unknown>;
}
// TODO: write tests
export class PageParam<V = any> {
export class PageParam<Value = any> {
readonly name: string;
readonly isMulti: boolean;
constructor(private init: PageParamInit<V>, private history: ObservableHistory<unknown>) {
constructor(protected readonly dependencies: PageParamDependencies, private init: PageParamInit<Value>) {
makeObservable(this);
const { name, defaultValue } = init;
@ -28,11 +32,11 @@ export class PageParam<V = any> {
}
// should be a getter since `init.defaultValue` could be a getter too
get defaultValue(): V | undefined {
get defaultValue(): Value | undefined {
return this.init.defaultValue;
}
parse(values: string | string[]): V {
parse(values: string | string[]): Value {
const { parse } = this.init;
if (parse) {
@ -40,10 +44,10 @@ export class PageParam<V = any> {
}
// return as-is ("string"-value based params)
return values as any as V;
return values as unknown as Value;
}
stringify(value: V = this.get()): string[] {
stringify(value: Value = this.get()): string[] {
const { stringify } = this.init;
if (stringify) {
@ -53,17 +57,17 @@ export class PageParam<V = any> {
return [value].flat().map(String);
}
get(): V {
get(): Value {
// TODO: cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.parse(this.getRaw()) ?? this.defaultValue!;
}
@action
set(value: V, { mergeGlobals = true, replaceHistory = false } = {}): void {
set(value: Value, { mergeGlobals = true, replaceHistory = false } = {}): void {
const search = this.toString({ mergeGlobals, value });
this.history.merge({ search }, replaceHistory);
this.dependencies.history.merge({ search }, replaceHistory);
}
/**
@ -77,10 +81,10 @@ export class PageParam<V = any> {
if (this.isMulti) {
this.clear();
values.forEach(value => {
this.history.searchParams.append(this.name, value);
this.dependencies.history.searchParams.append(this.name, value);
});
} else {
this.history.searchParams.set(this.name, values[0]);
this.dependencies.history.searchParams.set(this.name, values[0]);
}
}
@ -88,21 +92,21 @@ export class PageParam<V = any> {
* Get stringified raw value(s) from `document.location.search`
*/
getRaw(): string | string[] {
const values: string[] = this.history.searchParams.getAll(this.name);
const values: string[] = this.dependencies.history.searchParams.getAll(this.name);
return this.isMulti ? values : values[0];
}
@action
clear() {
this.history.searchParams.delete(this.name);
this.dependencies.history.searchParams.delete(this.name);
}
toString({ mergeGlobals = true, value = this.get() } = {}): string {
let searchParams = new URLSearchParams();
if (mergeGlobals) {
searchParams = new URLSearchParams(this.history.searchParams);
searchParams = new URLSearchParams(this.dependencies.history.searchParams);
searchParams.delete(this.name);
}

View File

@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import observableHistoryInjectable from "../navigation/history/observable.injectable";
import observableHistoryInjectable from "../navigation/observable-history.injectable";
const currentPathInjectable = getInjectable({
id: "current-path",

View File

@ -5,11 +5,10 @@
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { pipeline } from "@ogre-tools/fp";
import type { PageParamInit } from "../navigation";
import { PageParam } from "../navigation";
import observableHistoryInjectable from "../navigation/history/observable.injectable";
import type { LensRendererExtension } from "../../extensions/lens-renderer-extension";
import type { PageRegistration } from "../../extensions/registries";
import { fromPairs, map, toPairs } from "lodash/fp";
import { fromPairs, map } from "lodash/fp";
import createPageParamInjectable from "../navigation/create-page-param.injectable";
interface InstantiationParameter {
extension: LensRendererExtension;
@ -20,18 +19,18 @@ const extensionPageParametersInjectable = getInjectable({
id: "extension-page-parameters",
instantiate: (di, { registration }: InstantiationParameter) => {
const observableHistory = di.inject(observableHistoryInjectable);
const createPageParam = di.inject(createPageParamInjectable);
return pipeline(
registration.params ?? {},
toPairs,
map(([key, value]): [string, PageParamInit] => [
Object.entries,
map(([key, value]): [string, PageParamInit<unknown>] => [
key,
typeof value === "string"
? convertStringToPageParamInit(key, value)
: convertPartialPageParamInitToFull(key, value as PageParamInit),
: convertPartialPageParamInitToFull(key, value),
]),
map(([key, value]) => [key, new PageParam(value, observableHistory)]),
map(([key, value]) => [key, createPageParam(value)]),
fromPairs,
);
},
@ -44,20 +43,20 @@ const extensionPageParametersInjectable = getInjectable({
}),
});
const convertPartialPageParamInitToFull = (
const convertPartialPageParamInitToFull = <V>(
key: string,
value: PageParamInit,
): PageParamInit => ({
name: key,
defaultValue: value.defaultValue,
stringify: value.stringify,
parse: value.parse,
});
value: PageParamInit<V>,
): PageParamInit<V> => ({
name: key,
defaultValue: value.defaultValue,
stringify: value.stringify,
parse: value.parse,
});
const convertStringToPageParamInit = (
key: string,
value: string,
): PageParamInit => ({
): PageParamInit<string> => ({
name: key,
defaultValue: value,
});

View File

@ -10,8 +10,6 @@ import { observer } from "mobx-react";
import React from "react";
import { isEmpty, matches } from "lodash/fp";
import type { PageRegistration } from "../../extensions/registries";
import observableHistoryInjectable from "../navigation/observable-history.injectable";
import type { ObservableHistory } from "mobx-observable-history";
import { extensionRegistratorInjectionToken } from "../../extensions/extension-loader/extension-registrator-injection-token";
import { SiblingsInTabLayout } from "../components/layout/siblings-in-tab-layout";
import extensionPageParametersInjectable from "./extension-page-parameters.injectable";
@ -24,14 +22,11 @@ const extensionRouteRegistratorInjectable = getInjectable({
id: "extension-route-registrator",
instantiate: (di) => {
const observableHistory = di.inject(observableHistoryInjectable);
return (ext, extensionInstallationCount) => {
const extension = ext as LensRendererExtension;
const toRouteInjectable = toRouteInjectableFor(
di,
extension,
observableHistory,
extensionInstallationCount,
);
@ -53,7 +48,6 @@ const toRouteInjectableFor =
(
di: DiContainerForInstantiate,
extension: LensRendererExtension,
observableHistory: ObservableHistory<unknown>,
extensionInstallationCount: number,
) =>
(clusterFrame: boolean) =>

View File

@ -5,6 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import observableHistoryInjectable from "../navigation/observable-history.injectable";
import { runInAction } from "mobx";
import type { NavigateToUrl } from "../../common/front-end-routing/navigate-to-url-injection-token";
import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token";
import { broadcastMessage } from "../../common/ipc";
import { IpcRendererNavigationEvents } from "../navigation/events";
@ -12,24 +13,20 @@ import { IpcRendererNavigationEvents } from "../navigation/events";
const navigateToUrlInjectable = getInjectable({
id: "navigate-to-url",
instantiate: (di) => {
instantiate: (di): NavigateToUrl => {
const observableHistory = di.inject(observableHistoryInjectable);
return (url, options = {}) => {
return (url, options = {}): void => {
if (options.forceRootFrame) {
broadcastMessage(IpcRendererNavigationEvents.NAVIGATE_IN_APP, url);
return;
return void broadcastMessage(IpcRendererNavigationEvents.NAVIGATE_IN_APP, url);
}
runInAction(() => {
if (options.withoutAffectingBackButton) {
observableHistory.replace(url);
return;
} else {
observableHistory.push(url);
}
observableHistory.push(url);
});
};
},

View File

@ -13,11 +13,7 @@ const queryParametersInjectable = getInjectable({
instantiate: (di) => {
const observableHistory = di.inject(observableHistoryInjectable);
return computed(() => {
const queryString = observableHistory.location.search;
return parseQueryString(queryString);
});
return computed(() => parseQueryString(observableHistory.location.search));
},
});