UNPKG

@stolostron/multicluster-sdk

Version:

Provides extensions and APIs that dynamic plugins can use to leverage multicluster capabilities provided by Red Hat Advanced Cluster Management.

144 lines 7.62 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FleetResourceLink = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const dynamic_plugin_sdk_1 = require("@openshift-console/dynamic-plugin-sdk"); const classnames_1 = __importDefault(require("classnames")); const searchPaths_1 = require("../internal/search/searchPaths"); const useHubClusterName_1 = require("../api/useHubClusterName"); const useIsFleetAvailable_1 = require("../api/useIsFleetAvailable"); const react_router_dom_v5_compat_1 = require("react-router-dom-v5-compat"); const resourceRouteUtils_1 = require("../internal/resourceRouteUtils"); /** * Enhanced ResourceLink component for ACM fleet environments. * * Unlike the standard OpenShift ResourceLink which always links to the OpenShift console, * FleetResourceLink provides intelligent routing based on cluster context: * - First-class ACM resources (ManagedCluster) get direct links in all cases * - For hub clusters: Extension-based routing first, then fallback to OpenShift console * - For managed clusters: Extension-based routing first, then fallback to ACM search results * * This prevents users from having to jump between different consoles when managing * multi-cluster resources. * * @see https://github.com/openshift/console/blob/main/frontend/packages/console-dynamic-plugin-sdk/docs/api.md#resourcelink * * @param props - FleetResourceLinkProps extending ResourceLinkProps with cluster information * @param props.cluster - the target cluster name for the resource * @param props.groupVersionKind - K8s GroupVersionKind for the resource * @param props.name - the resource name * @param props.namespace - the resource namespace (required for namespaced resources) * @param props.displayName - optional display name override * @param props.className - additional CSS classes * @param props.inline - whether to display inline * @param props.hideIcon - whether to hide the resource icon * @param props.children - additional content to render * * @example * ```typescript * // Hub cluster VirtualMachine - routes to ACM VM page via extension system * <FleetResourceLink * name="my-vm" * namespace="default" * groupVersionKind={{ group: 'kubevirt.io', version: 'v1', kind: 'VirtualMachine' }} * /> * * // Managed cluster VirtualMachine - routes to ACM search results * <FleetResourceLink * name="remote-vm" * namespace="default" * cluster="prod-cluster" * groupVersionKind={{ group: 'kubevirt.io', version: 'v1', kind: 'VirtualMachine' }} * /> * * // ManagedCluster resource (lives on hub) - cluster prop omitted * <FleetResourceLink * name="prod-cluster" * groupVersionKind={{ group: 'cluster.open-cluster-management.io', version: 'v1', kind: 'ManagedCluster' }} * /> * ``` */ const FleetResourceLink = ({ cluster, ...resourceLinkProps }) => { const [hubClusterName, hubLoaded] = (0, useHubClusterName_1.useHubClusterName)(); const [resourceRoutes, resourceRoutesResolved] = (0, dynamic_plugin_sdk_1.useResolvedExtensions)(resourceRouteUtils_1.isResourceRoute); const isFleetAvailable = (0, useIsFleetAvailable_1.useIsFleetAvailable)(); if (!isFleetAvailable) { return (0, jsx_runtime_1.jsx)(dynamic_plugin_sdk_1.ResourceLink, { ...resourceLinkProps }); } const { className, displayName, inline = false, groupVersionKind, name, nameSuffix, namespace, hideIcon, title, children, dataTest, onClick, truncate, } = resourceLinkProps; const value = displayName || name; const classes = (0, classnames_1.default)('co-resource-item', className || '', { 'co-resource-item--inline': inline, 'co-resource-item--truncate': truncate, }); // if cluster name is given but hub name is not loaded yet, show text if (cluster && !hubLoaded) { return ((0, jsx_runtime_1.jsxs)("span", { className: classes, children: [!hideIcon && (0, jsx_runtime_1.jsx)(dynamic_plugin_sdk_1.ResourceIcon, { groupVersionKind: groupVersionKind }), (0, jsx_runtime_1.jsxs)("span", { className: "co-resource-item__resource-name", children: [value, nameSuffix] }), children] })); } // determine if this is a hub cluster case (if no cluster or it matches hub name) const isHubCluster = !cluster || cluster === hubClusterName; const getResourcePath = () => { if (!name || !groupVersionKind?.kind) { return null; } if (isHubCluster) { // hub cluster case, extension-based routing for hub cluster resources if (resourceRoutesResolved && resourceRoutes?.length) { const extensionPath = (0, resourceRouteUtils_1.getExtensionResourcePath)(resourceRoutes, groupVersionKind.group, groupVersionKind.kind, groupVersionKind.version, { cluster: cluster ?? hubClusterName ?? '', namespace, name, resource: { cluster: cluster ?? hubClusterName, namespace, name, ...groupVersionKind }, model: { group: groupVersionKind.group, version: groupVersionKind.version, kind: groupVersionKind.kind, }, }); if (extensionPath) { return extensionPath; } } // for hub cluster resources without extension handlers, return null to fallback to ResourceLink return null; } else { // managed cluster case, extensions first, then fallback to search if (resourceRoutesResolved && resourceRoutes?.length) { const extensionPath = (0, resourceRouteUtils_1.getExtensionResourcePath)(resourceRoutes, groupVersionKind.group, groupVersionKind.kind, groupVersionKind.version, { cluster, namespace, name, resource: { cluster, namespace, name, ...groupVersionKind }, model: { group: groupVersionKind.group, version: groupVersionKind.version, kind: groupVersionKind.kind, }, }); if (extensionPath) { return extensionPath; } } // fallback to search results for managed cluster resources return `/multicloud/search/resources${(0, searchPaths_1.getURLSearchParam)({ cluster, kind: groupVersionKind.kind, apigroup: groupVersionKind.group, apiversion: groupVersionKind.version, name, namespace, })}`; } }; const path = getResourcePath(); if (!path) { return (0, jsx_runtime_1.jsx)(dynamic_plugin_sdk_1.ResourceLink, { ...resourceLinkProps }); } return ((0, jsx_runtime_1.jsxs)("span", { className: classes, children: [!hideIcon && (0, jsx_runtime_1.jsx)(dynamic_plugin_sdk_1.ResourceIcon, { groupVersionKind: groupVersionKind }), (0, jsx_runtime_1.jsxs)(react_router_dom_v5_compat_1.Link, { to: path, title: title, className: "co-resource-item__resource-name", "data-test-id": value, "data-test": dataTest ?? value, onClick: onClick, children: [value, nameSuffix] }), children] })); }; exports.FleetResourceLink = FleetResourceLink; //# sourceMappingURL=FleetResourceLink.js.map