Path: blob/master/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx
11554 views
/*1* Copyright 2023 The Backstage Authors2*3* Licensed under the Apache License, Version 2.0 (the "License");4* you may not use this file except in compliance with the License.5* You may obtain a copy of the License at6*7* http://www.apache.org/licenses/LICENSE-2.08*9* Unless required by applicable law or agreed to in writing, software10* distributed under the License is distributed on an "AS IS" BASIS,11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12* See the License for the specific language governing permissions and13* limitations under the License.14*/1516import { ApiEntity } from '@backstage/catalog-model';17import { useApi } from '@backstage/core-plugin-api';18import Box from '@material-ui/core/Box';19import Button from '@material-ui/core/Button';20import Dialog from '@material-ui/core/Dialog';21import DialogActions from '@material-ui/core/DialogActions';22import DialogContent from '@material-ui/core/DialogContent';23import DialogTitle from '@material-ui/core/DialogTitle';24import Tab from '@material-ui/core/Tab';25import Tabs from '@material-ui/core/Tabs';26import Typography from '@material-ui/core/Typography';27import { makeStyles } from '@material-ui/core/styles';28import { ReactNode, useState, useEffect } from 'react';29import { apiDocsConfigRef } from '../../config';30import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';31import { useTranslationRef } from '@backstage/frontend-plugin-api';32import { apiDocsTranslationRef } from '../../translation';3334const useStyles = makeStyles(theme => ({35fullHeightDialog: {36height: 'calc(100% - 64px)',37},38root: {39display: 'flex',40flexGrow: 1,41width: '100%',42height: '100%',43},44tabs: {45borderRight: `1px solid ${theme.palette.divider}`,46flexShrink: 0,47},48tabContents: {49flexGrow: 1,50overflowX: 'auto',51},52title: {53color: theme.palette.text.primary,54wordBreak: 'break-word',55fontSize: theme.typography.h3.fontSize,56marginBottom: 0,57},58type: {59textTransform: 'uppercase',60fontSize: 11,61opacity: 0.8,62marginBottom: theme.spacing(1),63color: theme.palette.text.primary,64},65}));6667function TabPanel(props: {68children?: ReactNode;69index: number;70value: number;71}) {72const { children, value, index, ...other } = props;73const classes = useStyles();74return (75<div76role="tabpanel"77hidden={value !== index}78id={`vertical-tabpanel-${index}`}79aria-labelledby={`vertical-tab-${index}`}80className={classes.tabContents}81{...other}82>83{value === index && (84<Box pl={3} pr={3}>85{children}86</Box>87)}88</div>89);90}9192function a11yProps(index: number) {93return {94id: `vertical-tab-${index}`,95'aria-controls': `vertical-tabpanel-${index}`,96};97}9899/**100* A dialog that lets users inspect the API definition.101*102* @public103*/104export function ApiDefinitionDialog(props: {105open: boolean;106entity: ApiEntity;107onClose: () => void;108}) {109const { open, entity, onClose } = props;110const [activeTab, setActiveTab] = useState(0);111const classes = useStyles();112const { t } = useTranslationRef(apiDocsTranslationRef);113114useEffect(() => {115setActiveTab(0);116}, [open]);117118const config = useApi(apiDocsConfigRef);119const definitionWidget = config.getApiDefinitionWidget(entity);120121let tabIndex = 0;122let tabPanelIndex = 0;123124return (125<Dialog126fullWidth127maxWidth="xl"128open={open}129onClose={onClose}130aria-labelledby="api-definition-dialog-title"131PaperProps={{ className: classes.fullHeightDialog }}132>133<DialogTitle id="api-definition-dialog-title" disableTypography>134<Typography className={classes.type}>135API - {definitionWidget?.title ?? 'Raw'}136</Typography>137<Typography className={classes.title} variant="h1">138{entity.metadata.title ?? entity.metadata.name}139</Typography>140</DialogTitle>141<DialogContent dividers className={classes.root}>142<Tabs143orientation="vertical"144variant="scrollable"145value={activeTab}146onChange={(_, newValue) => setActiveTab(newValue)}147aria-label={t('apiDefinitionDialog.tabsAriaLabel')}148className={classes.tabs}149>150{definitionWidget ? (151<Tab label={definitionWidget.title} {...a11yProps(tabIndex++)} />152) : null}153<Tab label="Raw" {...a11yProps(tabIndex++)} />154</Tabs>155156{definitionWidget ? (157<TabPanel value={activeTab} index={tabPanelIndex++}>158{definitionWidget.component(entity.spec.definition)}159</TabPanel>160) : null}161<TabPanel value={activeTab} index={tabPanelIndex++}>162<PlainApiDefinitionWidget163definition={entity.spec.definition}164language={definitionWidget?.rawLanguage ?? entity.spec.type}165/>166</TabPanel>167</DialogContent>168<DialogActions>169<Button onClick={onClose} color="primary">170{t('apiDefinitionDialog.closeButtonTitle')}171</Button>172</DialogActions>173</Dialog>174);175}176177178