ApiDocsPage.tsx 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { useMemo } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { Card, Col, ConfigProvider, Layout, Row, Typography } from 'antd';
  4. import SwaggerUI from 'swagger-ui-react';
  5. import 'swagger-ui-react/swagger-ui.css';
  6. import { useTheme } from '@/hooks/useTheme';
  7. import AppSidebar from '@/layouts/AppSidebar';
  8. import { EXAMPLES } from '@/generated/examples';
  9. import { buildWebSocketEvents } from './websocket-events';
  10. import './ApiDocsPage.css';
  11. const basePath = window.X_UI_BASE_PATH || '';
  12. const openApiUrl = `${basePath}panel/api/openapi.json`;
  13. const websocketEvents = buildWebSocketEvents(EXAMPLES);
  14. export default function ApiDocsPage() {
  15. const { isDark, isUltra, antdThemeConfig } = useTheme();
  16. const { t } = useTranslation();
  17. const pageClass = useMemo(() => {
  18. const classes = ['api-docs-page'];
  19. if (isDark) classes.push('is-dark');
  20. if (isUltra) classes.push('is-ultra');
  21. return classes.join(' ');
  22. }, [isDark, isUltra]);
  23. return (
  24. <ConfigProvider theme={antdThemeConfig}>
  25. <Layout className={pageClass}>
  26. <AppSidebar />
  27. <Layout className="content-shell">
  28. <Layout.Content className="content-area">
  29. <section className="websocket-events" aria-labelledby="websocket-events-title">
  30. <Typography.Title id="websocket-events-title" level={2}>
  31. WebSocket events
  32. </Typography.Title>
  33. <Typography.Paragraph>
  34. After the cookie-authenticated <Typography.Text code>GET /ws</Typography.Text>{' '}
  35. upgrade, every server message uses{' '}
  36. <Typography.Text code>{'{ type, payload, time }'}</Typography.Text>. The time value
  37. is Unix milliseconds.
  38. </Typography.Paragraph>
  39. <Row gutter={[12, 12]}>
  40. {websocketEvents.map((event) => (
  41. <Col key={event.type} xs={24} sm={12} xl={8}>
  42. <Card size="small" title={<Typography.Text code>{event.type}</Typography.Text>}>
  43. <Typography.Paragraph>{event.summary}</Typography.Paragraph>
  44. <pre>{JSON.stringify(event.example, null, 2)}</pre>
  45. </Card>
  46. </Col>
  47. ))}
  48. </Row>
  49. </section>
  50. <div className="docs-wrapper" role="region" aria-label={t('menu.apiDocs')}>
  51. <SwaggerUI
  52. url={openApiUrl}
  53. docExpansion="list"
  54. deepLinking={false}
  55. tryItOutEnabled
  56. persistAuthorization
  57. />
  58. </div>
  59. </Layout.Content>
  60. </Layout>
  61. </Layout>
  62. </ConfigProvider>
  63. );
  64. }