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:
parent
b3cf868078
commit
fd86ea0d97
@ -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 apiVersion = "catalog.k8slens.dev/v1alpha1";
|
||||||
public readonly kind = "CatalogCategory";
|
public readonly kind = "CatalogCategory";
|
||||||
public metadata = {
|
public metadata = {
|
||||||
@ -151,5 +151,3 @@ class KubernetesClusterCategory extends CatalogCategory {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const kubernetesClusterCategory = new KubernetesClusterCategory();
|
|
||||||
|
|||||||
15
src/common/catalog/categories/general.injectable.ts
Normal file
15
src/common/catalog/categories/general.injectable.ts
Normal 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;
|
||||||
@ -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;
|
||||||
15
src/common/catalog/categories/weblink.injectable.ts
Normal file
15
src/common/catalog/categories/weblink.injectable.ts
Normal 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;
|
||||||
@ -2,18 +2,25 @@
|
|||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||||
import { GeneralCategory, kubernetesClusterCategory, WebLinkCategory } from "../catalog-entities";
|
import { WebLinkCategory } from "../catalog-entities";
|
||||||
|
import type { CatalogCategory } from "./catalog-entity";
|
||||||
import { CatalogCategoryRegistry } from "./category-registry";
|
import { CatalogCategoryRegistry } from "./category-registry";
|
||||||
|
|
||||||
|
export const builtInCategoryInjectionToken = getInjectionToken<CatalogCategory>({
|
||||||
|
id: "built-in-category-token",
|
||||||
|
});
|
||||||
|
|
||||||
const catalogCategoryRegistryInjectable = getInjectable({
|
const catalogCategoryRegistryInjectable = getInjectable({
|
||||||
id: "catalog-category-registry",
|
id: "catalog-category-registry",
|
||||||
instantiate: () => {
|
instantiate: (di) => {
|
||||||
const registry = new CatalogCategoryRegistry();
|
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());
|
registry.add(new WebLinkCategory());
|
||||||
|
|
||||||
return registry;
|
return registry;
|
||||||
|
|||||||
@ -3,13 +3,17 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* 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 {
|
export {
|
||||||
KubernetesCluster,
|
KubernetesCluster,
|
||||||
kubernetesClusterCategory,
|
|
||||||
GeneralEntity,
|
GeneralEntity,
|
||||||
WebLink,
|
WebLink,
|
||||||
} from "../../common/catalog-entities";
|
} from "../../common/catalog-entities";
|
||||||
|
|
||||||
|
export const kubernetesClusterCategory = asLegacyGlobalForExtensionApi(kubernetesClusterCategoryInjectable);
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
KubernetesClusterPrometheusMetrics,
|
KubernetesClusterPrometheusMetrics,
|
||||||
KubernetesClusterSpec,
|
KubernetesClusterSpec,
|
||||||
|
|||||||
@ -40,6 +40,6 @@ export interface RegisteredPage {
|
|||||||
id: string;
|
id: string;
|
||||||
extensionId: string;
|
extensionId: string;
|
||||||
url: string; // registered extension's page URL (without page params)
|
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
|
components: PageComponents; // normalized components
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,14 +3,20 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { PageParamInit } from "../../renderer/navigation";
|
import getDetailsUrlInjectable from "../../renderer/components/kube-detail-params/get-details-url.injectable";
|
||||||
import { navigation, PageParam } from "../../renderer/navigation";
|
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 type { PageParamInit, PageParam } from "../../renderer/navigation";
|
||||||
export { navigate, isActiveRoute } from "../../renderer/navigation/helpers";
|
|
||||||
export { hideDetails, showDetails, getDetailsUrl } from "../../renderer/components/kube-detail-params";
|
|
||||||
export type { URLParams } from "../../common/utils/buildUrl";
|
export type { URLParams } from "../../common/utils/buildUrl";
|
||||||
|
|
||||||
export function createPageParam<V>(init: PageParamInit<V>) {
|
export const getDetailsUrl = asLegacyGlobalFunctionForExtensionApi(getDetailsUrlInjectable);
|
||||||
return new PageParam<V>(init, navigation);
|
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);
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
||||||
@ -45,6 +45,7 @@ import { bindEvents } from "./navigation/events";
|
|||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import openDeleteClusterDialogInjectable from "./components/delete-cluster-dialog/open.injectable";
|
import openDeleteClusterDialogInjectable from "./components/delete-cluster-dialog/open.injectable";
|
||||||
import { init } from "@sentry/electron/renderer";
|
import { init } from "@sentry/electron/renderer";
|
||||||
|
import kubernetesClusterCategoryInjectable from "../common/catalog/categories/kubernetes-cluster.injectable";
|
||||||
|
|
||||||
configurePackages(); // global packages
|
configurePackages(); // global packages
|
||||||
registerCustomThemes(); // monaco editor themes
|
registerCustomThemes(); // monaco editor themes
|
||||||
@ -95,13 +96,11 @@ export async function bootstrap(di: DiContainer) {
|
|||||||
logger.info(`${logPrefix} initializing CatalogEntityDetailRegistry`);
|
logger.info(`${logPrefix} initializing CatalogEntityDetailRegistry`);
|
||||||
initializers.initCatalogEntityDetailRegistry();
|
initializers.initCatalogEntityDetailRegistry();
|
||||||
|
|
||||||
const navigateToAddCluster = di.inject(navigateToAddClusterInjectable);
|
|
||||||
const addSyncEntries = di.inject(addSyncEntriesInjectable);
|
|
||||||
|
|
||||||
logger.info(`${logPrefix} initializing CatalogCategoryRegistryEntries`);
|
logger.info(`${logPrefix} initializing CatalogCategoryRegistryEntries`);
|
||||||
initializers.initCatalogCategoryRegistryEntries({
|
initializers.initCatalogCategoryRegistryEntries({
|
||||||
navigateToAddCluster,
|
navigateToAddCluster: di.inject(navigateToAddClusterInjectable),
|
||||||
addSyncEntries,
|
addSyncEntries: di.inject(addSyncEntriesInjectable),
|
||||||
|
kubernetesClusterCategory: di.inject(kubernetesClusterCategoryInjectable),
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`${logPrefix} initializing Catalog`);
|
logger.info(`${logPrefix} initializing Catalog`);
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import { cssNames, prevDefault } from "../../utils";
|
|||||||
import type { ItemObject } from "../../../common/item.store";
|
import type { ItemObject } from "../../../common/item.store";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import type { ThemeStore } from "../../themes/store";
|
import type { ThemeStore } from "../../themes/store";
|
||||||
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
|
|
||||||
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
||||||
import { KubeObjectAge } from "../kube-object/age";
|
import { KubeObjectAge } from "../kube-object/age";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
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 apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||||
import eventStoreInjectable from "../+events/store.injectable";
|
import eventStoreInjectable from "../+events/store.injectable";
|
||||||
import nodeStoreInjectable from "../+nodes/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 {
|
export interface ClusterIssuesProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -49,6 +52,8 @@ interface Dependencies {
|
|||||||
nodeStore: NodeStore;
|
nodeStore: NodeStore;
|
||||||
eventStore: EventStore;
|
eventStore: EventStore;
|
||||||
apiManager: ApiManager;
|
apiManager: ApiManager;
|
||||||
|
kubeSelectedUrlParam: PageParam<string>;
|
||||||
|
toggleDetails: ToggleDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -86,6 +91,7 @@ class NonInjectedClusterIssues extends React.Component<ClusterIssuesProps & Depe
|
|||||||
|
|
||||||
getTableRow = (uid: string) => {
|
getTableRow = (uid: string) => {
|
||||||
const { warnings } = this;
|
const { warnings } = this;
|
||||||
|
const { kubeSelectedUrlParam, toggleDetails } = this.props;
|
||||||
const warning = warnings.find(warn => warn.getId() == uid);
|
const warning = warnings.find(warn => warn.getId() == uid);
|
||||||
|
|
||||||
if (!warning) {
|
if (!warning) {
|
||||||
@ -189,5 +195,7 @@ export const ClusterIssues = withInjectables<Dependencies, ClusterIssuesProps>(N
|
|||||||
apiManager: di.inject(apiManagerInjectable),
|
apiManager: di.inject(apiManagerInjectable),
|
||||||
eventStore: di.inject(eventStoreInjectable),
|
eventStore: di.inject(eventStoreInjectable),
|
||||||
nodeStore: di.inject(nodeStoreInjectable),
|
nodeStore: di.inject(nodeStoreInjectable),
|
||||||
|
kubeSelectedUrlParam: di.inject(kubeSelectedUrlParamInjectable),
|
||||||
|
toggleDetails: di.inject(toggleDetailsInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,13 +14,11 @@ const closePreferencesInjectable = getInjectable({
|
|||||||
const navigateToFrontPage = di.inject(navigateToFrontPageInjectable);
|
const navigateToFrontPage = di.inject(navigateToFrontPageInjectable);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (observableHistory.length === 1) {
|
if (observableHistory.length <= 1) {
|
||||||
navigateToFrontPage();
|
navigateToFrontPage();
|
||||||
|
} else {
|
||||||
return;
|
observableHistory.goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
observableHistory.goBack();
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -15,25 +15,25 @@ import { withInjectables } from "@ogre-tools/injectable-react";
|
|||||||
import { TopBar } from "../layout/top-bar/top-bar";
|
import { TopBar } from "../layout/top-bar/top-bar";
|
||||||
import catalogPreviousActiveTabStorageInjectable from "../+catalog/catalog-previous-active-tab-storage/catalog-previous-active-tab-storage.injectable";
|
import catalogPreviousActiveTabStorageInjectable from "../+catalog/catalog-previous-active-tab-storage/catalog-previous-active-tab-storage.injectable";
|
||||||
import type { IComputedValue } from "mobx";
|
import type { IComputedValue } from "mobx";
|
||||||
import { reaction } from "mobx";
|
|
||||||
import currentRouteComponentInjectable from "../../routes/current-route-component.injectable";
|
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 welcomeRouteInjectable from "../../../common/front-end-routing/routes/welcome/welcome-route.injectable";
|
||||||
import { buildURL } from "../../../common/utils/buildUrl";
|
import { buildURL } from "../../../common/utils/buildUrl";
|
||||||
import type { StorageLayer } from "../../utils";
|
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 {
|
interface Dependencies {
|
||||||
catalogPreviousActiveTabStorage: StorageLayer<string | null>;
|
catalogPreviousActiveTabStorage: StorageLayer<string | null>;
|
||||||
currentRouteComponent: IComputedValue<React.ElementType | undefined>;
|
currentRouteComponent: IComputedValue<React.ElementType | undefined>;
|
||||||
welcomeUrl: string;
|
welcomeUrl: string;
|
||||||
|
watchForGeneralEntityNavigation: WatchForGeneralEntityNavigation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class NonInjectedClusterManager extends React.Component<Dependencies> {
|
class NonInjectedClusterManager extends React.Component<Dependencies> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
disposeOnUnmount(this, [
|
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),
|
catalogPreviousActiveTabStorage: di.inject(catalogPreviousActiveTabStorageInjectable),
|
||||||
currentRouteComponent: di.inject(currentRouteComponentInjectable),
|
currentRouteComponent: di.inject(currentRouteComponentInjectable),
|
||||||
welcomeUrl: buildURL(di.inject(welcomeRouteInjectable).path),
|
welcomeUrl: buildURL(di.inject(welcomeRouteInjectable).path),
|
||||||
|
watchForGeneralEntityNavigation: di.inject(watchForGeneralEntityNavigationInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import drawerStorageInjectable, {
|
|||||||
defaultDrawerWidth,
|
defaultDrawerWidth,
|
||||||
} from "./drawer-storage/drawer-storage.injectable";
|
} from "./drawer-storage/drawer-storage.injectable";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
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";
|
import type { History } from "history";
|
||||||
|
|
||||||
export type DrawerPosition = "top" | "left" | "right" | "bottom";
|
export type DrawerPosition = "top" | "left" | "right" | "bottom";
|
||||||
|
|||||||
@ -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;
|
||||||
@ -2,12 +2,18 @@
|
|||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* 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 { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import showDetailsInjectable from "./show-details.injectable";
|
||||||
|
|
||||||
|
export type HideDetails = () => void;
|
||||||
|
|
||||||
const hideDetailsInjectable = getInjectable({
|
const hideDetailsInjectable = getInjectable({
|
||||||
id: "hide-details",
|
id: "hide-details",
|
||||||
instantiate: () => hideDetails,
|
instantiate: (di): HideDetails => {
|
||||||
|
const showDetails = di.inject(showDetailsInjectable);
|
||||||
|
|
||||||
|
return () => showDetails("");
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default hideDetailsInjectable;
|
export default hideDetailsInjectable;
|
||||||
@ -3,4 +3,16 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* 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);
|
||||||
|
|||||||
@ -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;
|
||||||
@ -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;
|
||||||
@ -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}`;
|
|
||||||
}
|
|
||||||
@ -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;
|
||||||
@ -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;
|
||||||
@ -11,37 +11,50 @@ import { computed, observable, reaction, makeObservable } from "mobx";
|
|||||||
import { Drawer } from "../drawer";
|
import { Drawer } from "../drawer";
|
||||||
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import { apiManager } from "../../../common/k8s-api/api-manager";
|
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
||||||
import { customResourceDefinitionStore } from "../+custom-resources/legacy-store";
|
|
||||||
import { KubeObjectMenu } from "../kube-object-menu";
|
import { KubeObjectMenu } from "../kube-object-menu";
|
||||||
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
||||||
import { CustomResourceDetails } from "../+custom-resources";
|
import { CustomResourceDetails } from "../+custom-resources";
|
||||||
import { KubeObjectMeta } from "../kube-object-meta";
|
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;
|
className?: string;
|
||||||
object: T;
|
object: Kube;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Dependencies {
|
||||||
|
kubeDetailsUrlParam: PageParam<string>;
|
||||||
|
apiManager: ApiManager;
|
||||||
|
hideDetails: HideDetails;
|
||||||
|
customResourceDefinitionStore: CustomResourceDefinitionStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class KubeObjectDetails extends React.Component {
|
class NonInjectedKubeObjectDetails extends React.Component<Dependencies> {
|
||||||
@observable isLoading = false;
|
@observable isLoading = false;
|
||||||
@observable.ref loadingError: React.ReactNode;
|
@observable.ref loadingError: React.ReactNode;
|
||||||
|
|
||||||
constructor(props: {}) {
|
constructor(props: Dependencies) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get path() {
|
@computed get path() {
|
||||||
return kubeDetailsUrlParam.get();
|
return this.props.kubeDetailsUrlParam.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get object() {
|
@computed get object() {
|
||||||
try {
|
try {
|
||||||
return apiManager
|
return this.props.apiManager
|
||||||
.getStore(this.path)
|
.getStore(this.path)
|
||||||
?.getByPath(this.path);
|
?.getByPath(this.path);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -56,13 +69,13 @@ export class KubeObjectDetails extends React.Component {
|
|||||||
reaction(() => [
|
reaction(() => [
|
||||||
this.path,
|
this.path,
|
||||||
this.object, // resource might be updated via watch-event or from already opened details
|
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 () => {
|
], async () => {
|
||||||
this.loadingError = "";
|
this.loadingError = "";
|
||||||
const { path, object } = this;
|
const { path, object } = this;
|
||||||
|
|
||||||
if (!object) {
|
if (!object) {
|
||||||
const store = apiManager.getStore(path);
|
const store = this.props.apiManager.getStore(path);
|
||||||
|
|
||||||
if (store) {
|
if (store) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
@ -103,7 +116,7 @@ export class KubeObjectDetails extends React.Component {
|
|||||||
));
|
));
|
||||||
|
|
||||||
if (details.length === 0) {
|
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
|
* 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)}
|
open={!!(object || isLoading || loadingError)}
|
||||||
title={this.renderTitle(object)}
|
title={this.renderTitle(object)}
|
||||||
toolbar={object && <KubeObjectMenu object={object} toolbar={true}/>}
|
toolbar={object && <KubeObjectMenu object={object} toolbar={true}/>}
|
||||||
onClose={hideDetails}
|
onClose={this.props.hideDetails}
|
||||||
>
|
>
|
||||||
{object && this.renderContents(object)}
|
{object && this.renderContents(object)}
|
||||||
</Drawer>
|
</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),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"
|
|||||||
import { KubeObjectMenu } from "../kube-object-menu";
|
import { KubeObjectMenu } from "../kube-object-menu";
|
||||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
|
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
|
||||||
import { ResourceKindMap, ResourceNames } from "../../utils/rbac";
|
import { ResourceKindMap, ResourceNames } from "../../utils/rbac";
|
||||||
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
|
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { TooltipPosition } from "../tooltip";
|
import { TooltipPosition } from "../tooltip";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
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 { SubscribableStore, SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||||
import type { KubeApi } from "../../../common/k8s-api/kube-api";
|
import type { KubeApi } from "../../../common/k8s-api/kube-api";
|
||||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
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<
|
export interface KubeObjectListLayoutProps<
|
||||||
K extends KubeObject,
|
K extends KubeObject,
|
||||||
@ -42,6 +45,8 @@ export interface KubeObjectListLayoutProps<
|
|||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
clusterFrameContext: ClusterFrameContext;
|
clusterFrameContext: ClusterFrameContext;
|
||||||
subscribeToStores: SubscribeStores;
|
subscribeToStores: SubscribeStores;
|
||||||
|
kubeSelectedUrlParam: PageParam<string>;
|
||||||
|
toggleDetails: ToggleDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -51,14 +56,13 @@ class NonInjectedKubeObjectListLayout<
|
|||||||
D extends KubeJsonApiDataFor<K>,
|
D extends KubeJsonApiDataFor<K>,
|
||||||
> extends React.Component<KubeObjectListLayoutProps<K, A, D> & Dependencies> {
|
> extends React.Component<KubeObjectListLayoutProps<K, A, D> & Dependencies> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onDetails: (item: KubeObject) => toggleDetails(item.selfLink),
|
|
||||||
subscribeStores: true,
|
subscribeStores: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
private loadErrors = observable.array<string>();
|
private loadErrors = observable.array<string>();
|
||||||
|
|
||||||
@computed get selectedItem() {
|
@computed get selectedItem() {
|
||||||
return this.props.store.getByPath(kubeSelectedUrlParam.get());
|
return this.props.store.getByPath(this.props.kubeSelectedUrlParam.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -104,7 +108,16 @@ class NonInjectedKubeObjectListLayout<
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
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;
|
const placeholderString = ResourceNames[ResourceKindMap[store.api.kind]] || store.api.kind;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -137,13 +150,14 @@ class NonInjectedKubeObjectListLayout<
|
|||||||
...[customizeHeader].filter(isDefined).flat(),
|
...[customizeHeader].filter(isDefined).flat(),
|
||||||
]}
|
]}
|
||||||
renderItemMenu={item => <KubeObjectMenu object={item} />}
|
renderItemMenu={item => <KubeObjectMenu object={item} />}
|
||||||
|
onDetails={onDetails ?? ((item) => toggleDetails(item.selfLink))}
|
||||||
{...layoutProps}
|
{...layoutProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const InjectedKubeObjectListLayout = withInjectables<
|
export const KubeObjectListLayout = withInjectables<
|
||||||
Dependencies,
|
Dependencies,
|
||||||
KubeObjectListLayoutProps<KubeObject, KubeApi<KubeObject, KubeJsonApiDataFor<KubeObject>>, KubeJsonApiDataFor<KubeObject>>
|
KubeObjectListLayoutProps<KubeObject, KubeApi<KubeObject, KubeJsonApiDataFor<KubeObject>>, KubeJsonApiDataFor<KubeObject>>
|
||||||
>(NonInjectedKubeObjectListLayout, {
|
>(NonInjectedKubeObjectListLayout, {
|
||||||
@ -151,13 +165,11 @@ const InjectedKubeObjectListLayout = withInjectables<
|
|||||||
...props,
|
...props,
|
||||||
clusterFrameContext: di.inject(clusterFrameContextInjectable),
|
clusterFrameContext: di.inject(clusterFrameContextInjectable),
|
||||||
subscribeToStores: di.inject(subscribeStoresInjectable),
|
subscribeToStores: di.inject(subscribeStoresInjectable),
|
||||||
|
kubeSelectedUrlParam: di.inject(kubeSelectedUrlParamInjectable),
|
||||||
|
toggleDetails: di.inject(toggleDetailsInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
}) as <
|
||||||
|
|
||||||
export function KubeObjectListLayout<
|
|
||||||
K extends KubeObject,
|
K extends KubeObject,
|
||||||
A extends KubeApi<K, D>,
|
A extends KubeApi<K, D>,
|
||||||
D extends KubeJsonApiDataFor<K> = KubeJsonApiDataFor<K>,
|
D extends KubeJsonApiDataFor<K> = KubeJsonApiDataFor<K>,
|
||||||
>(props: KubeObjectListLayoutProps<K, A, D>) {
|
>(props: KubeObjectListLayoutProps<K, A, D>) => React.ReactElement;
|
||||||
return <InjectedKubeObjectListLayout {...(props as never)} />;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -13,9 +13,10 @@ import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
|||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import clusterNameInjectable from "./dependencies/cluster-name.injectable";
|
import clusterNameInjectable from "./dependencies/cluster-name.injectable";
|
||||||
import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.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 kubeObjectMenuItemsInjectable from "./dependencies/kube-object-menu-items/kube-object-menu-items.injectable";
|
||||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.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 {
|
export interface KubeObjectMenuProps<TKubeObject extends KubeObject> extends MenuActionsProps {
|
||||||
object: TKubeObject;
|
object: TKubeObject;
|
||||||
@ -27,7 +28,7 @@ interface Dependencies {
|
|||||||
apiManager: ApiManager;
|
apiManager: ApiManager;
|
||||||
kubeObjectMenuItems: React.ElementType[];
|
kubeObjectMenuItems: React.ElementType[];
|
||||||
clusterName: string | undefined;
|
clusterName: string | undefined;
|
||||||
hideDetails: () => void;
|
hideDetails: HideDetails;
|
||||||
createEditResourceTab: (kubeObject: KubeObject) => void;
|
createEditResourceTab: (kubeObject: KubeObject) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { cssNames } from "../../utils";
|
|||||||
import { CloseButton } from "./close-button";
|
import { CloseButton } from "./close-button";
|
||||||
import { getLegacyGlobalDiForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
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 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> {
|
export interface SettingLayoutProps extends React.DOMAttributes<any> {
|
||||||
className?: IClassName;
|
className?: IClassName;
|
||||||
|
|||||||
@ -37,7 +37,7 @@ import { observable, toJS } from "mobx";
|
|||||||
import type { Draft } from "immer";
|
import type { Draft } from "immer";
|
||||||
import { produce, isDraft } from "immer";
|
import { produce, isDraft } from "immer";
|
||||||
import type { GetDiForUnitTestingOptions } from "../test-utils/get-dis-for-unit-testing";
|
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 {
|
export interface GetRendererDiForUnitTestingOptions extends GetDiForUnitTestingOptions {
|
||||||
overrideCreateStorage?: boolean;
|
overrideCreateStorage?: boolean;
|
||||||
|
|||||||
@ -3,16 +3,21 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* 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 { isLinux, isWindows } from "../../common/vars";
|
||||||
import { PathPicker } from "../components/path-picker";
|
import { PathPicker } from "../components/path-picker";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
navigateToAddCluster: () => void;
|
navigateToAddCluster: () => void;
|
||||||
addSyncEntries: (filePaths: string[]) => void;
|
addSyncEntries: (filePaths: string[]) => void;
|
||||||
|
kubernetesClusterCategory: KubernetesClusterCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initCatalogCategoryRegistryEntries({ navigateToAddCluster, addSyncEntries } : Dependencies) {
|
export function initCatalogCategoryRegistryEntries({
|
||||||
|
navigateToAddCluster,
|
||||||
|
addSyncEntries,
|
||||||
|
kubernetesClusterCategory,
|
||||||
|
} : Dependencies) {
|
||||||
kubernetesClusterCategory.on("catalogAddMenu", ctx => {
|
kubernetesClusterCategory.on("catalogAddMenu", ctx => {
|
||||||
ctx.menuItems.push(
|
ctx.menuItems.push(
|
||||||
{
|
{
|
||||||
|
|||||||
23
src/renderer/navigation/create-page-param.injectable.ts
Normal file
23
src/renderer/navigation/create-page-param.injectable.ts
Normal 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;
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
@ -3,8 +3,33 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* 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";
|
export * from "./page-param";
|
||||||
|
|||||||
20
src/renderer/navigation/is-route-active.injectable.ts
Normal file
20
src/renderer/navigation/is-route-active.injectable.ts
Normal 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;
|
||||||
21
src/renderer/navigation/match-route.injectable.ts
Normal file
21
src/renderer/navigation/match-route.injectable.ts
Normal 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;
|
||||||
32
src/renderer/navigation/navigate.injectable.ts
Normal file
32
src/renderer/navigation/navigate.injectable.ts
Normal 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;
|
||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { createObservableHistory } from "mobx-observable-history";
|
import { createObservableHistory } from "mobx-observable-history";
|
||||||
import loggerInjectable from "../../../common/logger.injectable";
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
import { searchParamsOptions } from "./search-params";
|
import { searchParamsOptions } from "./search-params";
|
||||||
import historyInjectable from "./history.injectable";
|
import historyInjectable from "./history.injectable";
|
||||||
|
|
||||||
@ -7,19 +7,23 @@
|
|||||||
import { action, makeObservable } from "mobx";
|
import { action, makeObservable } from "mobx";
|
||||||
import type { ObservableHistory } from "mobx-observable-history";
|
import type { ObservableHistory } from "mobx-observable-history";
|
||||||
|
|
||||||
export interface PageParamInit<V = any> {
|
export interface PageParamInit<Value = any> {
|
||||||
name: string;
|
name: string;
|
||||||
defaultValue?: V; // multi-values param must be defined with array-value, e.g. []
|
defaultValue?: Value; // multi-values param must be defined with array-value, e.g. []
|
||||||
parse?(value: string | string[]): V; // from URL
|
parse?(value: string | string[]): Value; // from URL
|
||||||
stringify?(value: V): string | string[]; // to URL
|
stringify?(value: Value): string | string[]; // to URL
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PageParamDependencies {
|
||||||
|
readonly history: ObservableHistory<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: write tests
|
// TODO: write tests
|
||||||
export class PageParam<V = any> {
|
export class PageParam<Value = any> {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly isMulti: boolean;
|
readonly isMulti: boolean;
|
||||||
|
|
||||||
constructor(private init: PageParamInit<V>, private history: ObservableHistory<unknown>) {
|
constructor(protected readonly dependencies: PageParamDependencies, private init: PageParamInit<Value>) {
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
const { name, defaultValue } = init;
|
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
|
// should be a getter since `init.defaultValue` could be a getter too
|
||||||
get defaultValue(): V | undefined {
|
get defaultValue(): Value | undefined {
|
||||||
return this.init.defaultValue;
|
return this.init.defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse(values: string | string[]): V {
|
parse(values: string | string[]): Value {
|
||||||
const { parse } = this.init;
|
const { parse } = this.init;
|
||||||
|
|
||||||
if (parse) {
|
if (parse) {
|
||||||
@ -40,10 +44,10 @@ export class PageParam<V = any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return as-is ("string"-value based params)
|
// 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;
|
const { stringify } = this.init;
|
||||||
|
|
||||||
if (stringify) {
|
if (stringify) {
|
||||||
@ -53,17 +57,17 @@ export class PageParam<V = any> {
|
|||||||
return [value].flat().map(String);
|
return [value].flat().map(String);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(): V {
|
get(): Value {
|
||||||
// TODO: cleanup
|
// TODO: cleanup
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
return this.parse(this.getRaw()) ?? this.defaultValue!;
|
return this.parse(this.getRaw()) ?? this.defaultValue!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
set(value: V, { mergeGlobals = true, replaceHistory = false } = {}): void {
|
set(value: Value, { mergeGlobals = true, replaceHistory = false } = {}): void {
|
||||||
const search = this.toString({ mergeGlobals, value });
|
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) {
|
if (this.isMulti) {
|
||||||
this.clear();
|
this.clear();
|
||||||
values.forEach(value => {
|
values.forEach(value => {
|
||||||
this.history.searchParams.append(this.name, value);
|
this.dependencies.history.searchParams.append(this.name, value);
|
||||||
});
|
});
|
||||||
} else {
|
} 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`
|
* Get stringified raw value(s) from `document.location.search`
|
||||||
*/
|
*/
|
||||||
getRaw(): string | string[] {
|
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];
|
return this.isMulti ? values : values[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
clear() {
|
clear() {
|
||||||
this.history.searchParams.delete(this.name);
|
this.dependencies.history.searchParams.delete(this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString({ mergeGlobals = true, value = this.get() } = {}): string {
|
toString({ mergeGlobals = true, value = this.get() } = {}): string {
|
||||||
let searchParams = new URLSearchParams();
|
let searchParams = new URLSearchParams();
|
||||||
|
|
||||||
if (mergeGlobals) {
|
if (mergeGlobals) {
|
||||||
searchParams = new URLSearchParams(this.history.searchParams);
|
searchParams = new URLSearchParams(this.dependencies.history.searchParams);
|
||||||
searchParams.delete(this.name);
|
searchParams.delete(this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { computed } from "mobx";
|
import { computed } from "mobx";
|
||||||
import observableHistoryInjectable from "../navigation/history/observable.injectable";
|
import observableHistoryInjectable from "../navigation/observable-history.injectable";
|
||||||
|
|
||||||
const currentPathInjectable = getInjectable({
|
const currentPathInjectable = getInjectable({
|
||||||
id: "current-path",
|
id: "current-path",
|
||||||
|
|||||||
@ -5,11 +5,10 @@
|
|||||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||||
import { pipeline } from "@ogre-tools/fp";
|
import { pipeline } from "@ogre-tools/fp";
|
||||||
import type { PageParamInit } from "../navigation";
|
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 { LensRendererExtension } from "../../extensions/lens-renderer-extension";
|
||||||
import type { PageRegistration } from "../../extensions/registries";
|
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 {
|
interface InstantiationParameter {
|
||||||
extension: LensRendererExtension;
|
extension: LensRendererExtension;
|
||||||
@ -20,18 +19,18 @@ const extensionPageParametersInjectable = getInjectable({
|
|||||||
id: "extension-page-parameters",
|
id: "extension-page-parameters",
|
||||||
|
|
||||||
instantiate: (di, { registration }: InstantiationParameter) => {
|
instantiate: (di, { registration }: InstantiationParameter) => {
|
||||||
const observableHistory = di.inject(observableHistoryInjectable);
|
const createPageParam = di.inject(createPageParamInjectable);
|
||||||
|
|
||||||
return pipeline(
|
return pipeline(
|
||||||
registration.params ?? {},
|
registration.params ?? {},
|
||||||
toPairs,
|
Object.entries,
|
||||||
map(([key, value]): [string, PageParamInit] => [
|
map(([key, value]): [string, PageParamInit<unknown>] => [
|
||||||
key,
|
key,
|
||||||
typeof value === "string"
|
typeof value === "string"
|
||||||
? convertStringToPageParamInit(key, value)
|
? 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,
|
fromPairs,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -44,20 +43,20 @@ const extensionPageParametersInjectable = getInjectable({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const convertPartialPageParamInitToFull = (
|
const convertPartialPageParamInitToFull = <V>(
|
||||||
key: string,
|
key: string,
|
||||||
value: PageParamInit,
|
value: PageParamInit<V>,
|
||||||
): PageParamInit => ({
|
): PageParamInit<V> => ({
|
||||||
name: key,
|
name: key,
|
||||||
defaultValue: value.defaultValue,
|
defaultValue: value.defaultValue,
|
||||||
stringify: value.stringify,
|
stringify: value.stringify,
|
||||||
parse: value.parse,
|
parse: value.parse,
|
||||||
});
|
});
|
||||||
|
|
||||||
const convertStringToPageParamInit = (
|
const convertStringToPageParamInit = (
|
||||||
key: string,
|
key: string,
|
||||||
value: string,
|
value: string,
|
||||||
): PageParamInit => ({
|
): PageParamInit<string> => ({
|
||||||
name: key,
|
name: key,
|
||||||
defaultValue: value,
|
defaultValue: value,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,8 +10,6 @@ import { observer } from "mobx-react";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { isEmpty, matches } from "lodash/fp";
|
import { isEmpty, matches } from "lodash/fp";
|
||||||
import type { PageRegistration } from "../../extensions/registries";
|
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 { extensionRegistratorInjectionToken } from "../../extensions/extension-loader/extension-registrator-injection-token";
|
||||||
import { SiblingsInTabLayout } from "../components/layout/siblings-in-tab-layout";
|
import { SiblingsInTabLayout } from "../components/layout/siblings-in-tab-layout";
|
||||||
import extensionPageParametersInjectable from "./extension-page-parameters.injectable";
|
import extensionPageParametersInjectable from "./extension-page-parameters.injectable";
|
||||||
@ -24,14 +22,11 @@ const extensionRouteRegistratorInjectable = getInjectable({
|
|||||||
id: "extension-route-registrator",
|
id: "extension-route-registrator",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const observableHistory = di.inject(observableHistoryInjectable);
|
|
||||||
|
|
||||||
return (ext, extensionInstallationCount) => {
|
return (ext, extensionInstallationCount) => {
|
||||||
const extension = ext as LensRendererExtension;
|
const extension = ext as LensRendererExtension;
|
||||||
const toRouteInjectable = toRouteInjectableFor(
|
const toRouteInjectable = toRouteInjectableFor(
|
||||||
di,
|
di,
|
||||||
extension,
|
extension,
|
||||||
observableHistory,
|
|
||||||
extensionInstallationCount,
|
extensionInstallationCount,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -53,7 +48,6 @@ const toRouteInjectableFor =
|
|||||||
(
|
(
|
||||||
di: DiContainerForInstantiate,
|
di: DiContainerForInstantiate,
|
||||||
extension: LensRendererExtension,
|
extension: LensRendererExtension,
|
||||||
observableHistory: ObservableHistory<unknown>,
|
|
||||||
extensionInstallationCount: number,
|
extensionInstallationCount: number,
|
||||||
) =>
|
) =>
|
||||||
(clusterFrame: boolean) =>
|
(clusterFrame: boolean) =>
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import observableHistoryInjectable from "../navigation/observable-history.injectable";
|
import observableHistoryInjectable from "../navigation/observable-history.injectable";
|
||||||
import { runInAction } from "mobx";
|
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 { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token";
|
||||||
import { broadcastMessage } from "../../common/ipc";
|
import { broadcastMessage } from "../../common/ipc";
|
||||||
import { IpcRendererNavigationEvents } from "../navigation/events";
|
import { IpcRendererNavigationEvents } from "../navigation/events";
|
||||||
@ -12,24 +13,20 @@ import { IpcRendererNavigationEvents } from "../navigation/events";
|
|||||||
const navigateToUrlInjectable = getInjectable({
|
const navigateToUrlInjectable = getInjectable({
|
||||||
id: "navigate-to-url",
|
id: "navigate-to-url",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di): NavigateToUrl => {
|
||||||
const observableHistory = di.inject(observableHistoryInjectable);
|
const observableHistory = di.inject(observableHistoryInjectable);
|
||||||
|
|
||||||
return (url, options = {}) => {
|
return (url, options = {}): void => {
|
||||||
if (options.forceRootFrame) {
|
if (options.forceRootFrame) {
|
||||||
broadcastMessage(IpcRendererNavigationEvents.NAVIGATE_IN_APP, url);
|
return void broadcastMessage(IpcRendererNavigationEvents.NAVIGATE_IN_APP, url);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
if (options.withoutAffectingBackButton) {
|
if (options.withoutAffectingBackButton) {
|
||||||
observableHistory.replace(url);
|
observableHistory.replace(url);
|
||||||
|
} else {
|
||||||
return;
|
observableHistory.push(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
observableHistory.push(url);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@ -13,11 +13,7 @@ const queryParametersInjectable = getInjectable({
|
|||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const observableHistory = di.inject(observableHistoryInjectable);
|
const observableHistory = di.inject(observableHistoryInjectable);
|
||||||
|
|
||||||
return computed(() => {
|
return computed(() => parseQueryString(observableHistory.location.search));
|
||||||
const queryString = observableHistory.location.search;
|
|
||||||
|
|
||||||
return parseQueryString(queryString);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user