catalog: add inspect dialog url

Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com>
This commit is contained in:
Vincenzo Scamporlino
2025-01-29 09:59:49 +01:00
parent 915f0f3ba8
commit 16bd94e038
2 changed files with 58 additions and 21 deletions
@@ -24,7 +24,7 @@ import DialogTitle from '@material-ui/core/DialogTitle';
import Tab from '@material-ui/core/Tab';
import Tabs from '@material-ui/core/Tabs';
import { makeStyles } from '@material-ui/core/styles';
import React, { useEffect } from 'react';
import React, { ComponentProps, useEffect } from 'react';
import { AncestryPage } from './components/AncestryPage';
import { ColocatedPage } from './components/ColocatedPage';
import { JsonPage } from './components/JsonPage';
@@ -85,6 +85,19 @@ function a11yProps(index: number) {
};
}
const tabNames: Record<
NonNullable<ComponentProps<typeof InspectEntityDialog>['initialTab']>,
string
> = {
overview: 'Overview',
ancestry: 'Ancestry',
colocated: 'Colocated',
json: 'Raw JSON',
yaml: 'Raw YAML',
} as const;
const tabs = Object.keys(tabNames) as Array<keyof typeof tabNames>;
/**
* A dialog that lets users inspect the low level details of their entities.
*
@@ -93,15 +106,20 @@ function a11yProps(index: number) {
export function InspectEntityDialog(props: {
open: boolean;
entity: Entity;
initialTab?: 'overview' | 'ancestry' | 'colocated' | 'json' | 'yaml';
onClose: () => void;
onSelect?: (tab: string) => void;
}) {
const classes = useStyles();
const [activeTab, setActiveTab] = React.useState(0);
const [activeTab, setActiveTab] = React.useState(
getTabIndex(tabs, props.initialTab),
);
const { t } = useTranslationRef(catalogReactTranslationRef);
useEffect(() => {
setActiveTab(0);
}, [props.open]);
getTabIndex(tabs, props.initialTab);
}, [props.open, props.initialTab]);
if (!props.entity) {
return null;
@@ -125,15 +143,16 @@ export function InspectEntityDialog(props: {
orientation="vertical"
variant="scrollable"
value={activeTab}
onChange={(_, newValue) => setActiveTab(newValue)}
onChange={(_, tabIndex) => {
setActiveTab(tabIndex);
props.onSelect?.(tabs[tabIndex]);
}}
aria-label="Inspector options"
className={classes.tabs}
>
<Tab label="Overview" {...a11yProps(0)} />
<Tab label="Ancestry" {...a11yProps(1)} />
<Tab label="Colocated" {...a11yProps(2)} />
<Tab label="Raw JSON" {...a11yProps(3)} />
<Tab label="Raw YAML" {...a11yProps(4)} />
{tabs.map((tab, index) => (
<Tab key={tab} label={tabNames[tab]} {...a11yProps(index)} />
))}
</Tabs>
<TabPanel value={activeTab} index={0}>
@@ -161,3 +180,10 @@ export function InspectEntityDialog(props: {
</Dialog>
);
}
function getTabIndex(
allTabs: string[],
initialTab: keyof typeof tabNames | undefined,
) {
return initialTab ? allTabs.indexOf(initialTab) : 0;
}
@@ -56,8 +56,8 @@ import Box from '@material-ui/core/Box';
import { makeStyles } from '@material-ui/core/styles';
import { TabProps } from '@material-ui/core/Tab';
import Alert from '@material-ui/lab/Alert';
import React, { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import React, { ComponentProps, useEffect, useState } from 'react';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
import useAsync from 'react-use/esm/useAsync';
import { catalogTranslationRef } from '../../alpha/translation';
import { rootRouteRef, unregisterRedirectRouteRef } from '../../routes';
@@ -284,15 +284,15 @@ export const EntityLayout = (props: EntityLayoutProps) => {
);
const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);
const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false);
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const catalogRoute = useRouteRef(rootRouteRef);
const unregisterRedirectRoute = useRouteRef(unregisterRedirectRouteRef);
const { t } = useTranslationRef(catalogTranslationRef);
const cleanUpAfterRemoval = async () => {
setConfirmationDialogOpen(false);
setInspectionDialogOpen(false);
navigate(
unregisterRedirectRoute ? unregisterRedirectRoute() : catalogRoute(),
);
@@ -318,10 +318,12 @@ export const EntityLayout = (props: EntityLayoutProps) => {
// to another entity.
useEffect(() => {
setConfirmationDialogOpen(false);
setInspectionDialogOpen(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.pathname]);
const selectedInspectTab = searchParams.get('inspect');
const showInspectTab = typeof selectedInspectTab === 'string';
return (
<Page themeId={entity?.spec?.type?.toString() ?? 'home'}>
<Header
@@ -353,7 +355,7 @@ export const EntityLayout = (props: EntityLayoutProps) => {
UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}
UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}
onUnregisterEntity={() => setConfirmationDialogOpen(true)}
onInspectEntity={() => setInspectionDialogOpen(true)}
onInspectEntity={() => setSearchParams('inspect')}
/>
</>
)}
@@ -385,17 +387,26 @@ export const EntityLayout = (props: EntityLayoutProps) => {
</Content>
)}
{showInspectTab && (
<InspectEntityDialog
entity={entity!}
initialTab={
(selectedInspectTab as ComponentProps<
typeof InspectEntityDialog
>['initialTab']) || undefined
}
onSelect={newTab => setSearchParams(`inspect=${newTab}`)}
open
onClose={() => setSearchParams()}
/>
)}
<UnregisterEntityDialog
open={confirmationDialogOpen}
entity={entity!}
onConfirm={cleanUpAfterRemoval}
onClose={() => setConfirmationDialogOpen(false)}
/>
<InspectEntityDialog
open={inspectionDialogOpen}
entity={entity!}
onClose={() => setInspectionDialogOpen(false)}
/>
</Page>
);
};