From dc3dba06658cab6ee2bc9ea504670155541af917 Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Sat, 20 Sep 2025 23:19:42 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20enhance(oauth2):=20improve=20UI=20c?= =?UTF-8?q?omponents=20and=20code=20display=20experience?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **Table Layout Optimization:** - Remove description column from OAuth2 client table to save space - Add tooltip on client name hover to display full description - Adjust table scroll width from 1200px to 1000px for better layout - Improve client name column width to 180px for better readability - **Action Button Simplification:** - Replace icon-only buttons with text labels for better accessibility - Simplify Popconfirm content by removing complex styled layouts - Remove unnecessary Tooltip wrappers around action buttons - Clean up unused Lucide icon imports (Edit, Key, Trash2) - **Code Display Enhancement:** - Replace basic
 tags with CodeViewer component in modal dialogs
  - Add syntax highlighting for JSON content in ServerInfoModal and JWKSInfoModal
  - Implement copy-to-clipboard functionality for server info and JWKS data
  - Add performance optimization for large content display
  - Provide expandable/collapsible interface for better UX

- **Component Architecture:**
  - Import and integrate CodeViewer component in both modal components
  - Set appropriate props: content, title, and language='json'
  - Maintain loading states and error handling functionality

- **Internationalization:**
  - Add English translations for new UI elements:
    * '暂无描述': 'No description'
    * 'OAuth2 服务器配置': 'OAuth2 Server Configuration'
    * 'JWKS 密钥集': 'JWKS Key Set'

- **User Experience Improvements:**
  - Enhanced tooltip interaction for description display
  - Better visual feedback with cursor-help styling
  - Improved code readability with professional dark theme
  - Consistent styling across all OAuth2 management interfaces

This update focuses on UI/UX improvements while maintaining full functionality and adding modern code viewing capabilities to the OAuth2 management system.
---
 .../{playground => common/ui}/CodeViewer.jsx  |   2 +-
 web/src/components/playground/DebugPanel.jsx  |   2 +-
 .../settings/oauth2/OAuth2ClientSettings.jsx  | 103 ++++--------------
 .../settings/oauth2/OAuth2ServerSettings.jsx  |  16 +--
 .../settings/oauth2/modals/JWKSInfoModal.jsx  |  33 ++----
 .../oauth2/modals/SecretDisplayModal.jsx      |  34 ++----
 .../oauth2/modals/ServerInfoModal.jsx         |  35 ++----
 .../personal/cards/NotificationSettings.jsx   |   2 +-
 web/src/i18n/locales/en.json                  |   5 +-
 9 files changed, 63 insertions(+), 169 deletions(-)
 rename web/src/components/{playground => common/ui}/CodeViewer.jsx (99%)

diff --git a/web/src/components/playground/CodeViewer.jsx b/web/src/components/common/ui/CodeViewer.jsx
similarity index 99%
rename from web/src/components/playground/CodeViewer.jsx
rename to web/src/components/common/ui/CodeViewer.jsx
index 9d8ae453a..b614d7c33 100644
--- a/web/src/components/playground/CodeViewer.jsx
+++ b/web/src/components/common/ui/CodeViewer.jsx
@@ -21,7 +21,7 @@ import React, { useState, useMemo, useCallback } from 'react';
 import { Button, Tooltip, Toast } from '@douyinfe/semi-ui';
 import { Copy, ChevronDown, ChevronUp } from 'lucide-react';
 import { useTranslation } from 'react-i18next';
-import { copy } from '../../helpers';
+import { copy } from '../../../helpers';
 
 const PERFORMANCE_CONFIG = {
   MAX_DISPLAY_LENGTH: 50000, // 最大显示字符数
diff --git a/web/src/components/playground/DebugPanel.jsx b/web/src/components/playground/DebugPanel.jsx
index d931ff61c..7f8fd0387 100644
--- a/web/src/components/playground/DebugPanel.jsx
+++ b/web/src/components/playground/DebugPanel.jsx
@@ -28,7 +28,7 @@ import {
 } from '@douyinfe/semi-ui';
 import { Code, Zap, Clock, X, Eye, Send } from 'lucide-react';
 import { useTranslation } from 'react-i18next';
-import CodeViewer from './CodeViewer';
+import CodeViewer from '../common/ui/CodeViewer';
 
 const DebugPanel = ({
   debugData,
diff --git a/web/src/components/settings/oauth2/OAuth2ClientSettings.jsx b/web/src/components/settings/oauth2/OAuth2ClientSettings.jsx
index def4df899..02e33cd03 100644
--- a/web/src/components/settings/oauth2/OAuth2ClientSettings.jsx
+++ b/web/src/components/settings/oauth2/OAuth2ClientSettings.jsx
@@ -31,7 +31,7 @@ import {
   Tooltip,
 } from '@douyinfe/semi-ui';
 import { IconSearch } from '@douyinfe/semi-icons';
-import { User, Grid3X3 } from 'lucide-react';
+import { User } from 'lucide-react';
 import { API, showError, showSuccess } from '../../../helpers';
 import CreateOAuth2ClientModal from './modals/CreateOAuth2ClientModal';
 import EditOAuth2ClientModal from './modals/EditOAuth2ClientModal';
@@ -138,13 +138,14 @@ export default function OAuth2ClientSettings() {
     {
       title: t('客户端名称'),
       dataIndex: 'name',
-      render: (name) => (
-        
+ render: (name, record) => ( +
- {name} + + {name} +
), - width: 150, }, { title: t('客户端ID'), @@ -154,30 +155,24 @@ export default function OAuth2ClientSettings() { {id} ), - width: 200, }, { - title: t('描述'), - dataIndex: 'description', - render: (description) => ( - - {description || '-'} - + title: t('状态'), + dataIndex: 'status', + render: (status) => ( + + {status === 1 ? t('启用') : t('禁用')} + ), - width: 150, }, { title: t('类型'), dataIndex: 'client_type', render: (text) => ( - + {text === 'confidential' ? t('机密客户端') : t('公开客户端')} ), - width: 120, }, { title: t('授权类型'), @@ -195,7 +190,7 @@ export default function OAuth2ClientSettings() { return (
{types.slice(0, 2).map((type) => ( - + {typeMap[type] || type} ))} @@ -206,7 +201,7 @@ export default function OAuth2ClientSettings() { .map((t) => typeMap[t] || t) .join(', ')} > - + +{types.length - 2} @@ -214,106 +209,54 @@ export default function OAuth2ClientSettings() {
); }, - width: 150, - }, - { - title: t('状态'), - dataIndex: 'status', - render: (status) => ( - - {status === 1 ? t('启用') : t('禁用')} - - ), - width: 80, }, { title: t('创建时间'), dataIndex: 'created_time', render: (time) => new Date(time * 1000).toLocaleString(), - width: 150, }, { title: t('操作'), render: (_, record) => ( {record.client_type === 'confidential' && ( -
- {t('客户端')}: - {record.name} -
-
- - ⚠️ {t('操作不可撤销,旧密钥将立即失效。')} - -
-
- } + content={t('操作不可撤销,旧密钥将立即失效。')} onConfirm={() => handleRegenerateSecret(record)} okText={t('确认')} cancelText={t('取消')} position='bottomLeft' > - )} -
- {t('客户端')}: - {record.name} -
-
- - 🗑️ {t('删除后无法恢复,相关 API 调用将立即失效。')} - -
- - } + content={t('删除后无法恢复,相关 API 调用将立即失效。')} onConfirm={() => handleDelete(record)} okText={t('确定删除')} cancelText={t('取消')} position='bottomLeft' > -
), - width: 140, fixed: 'right', }, ]; @@ -348,13 +291,13 @@ export default function OAuth2ClientSettings() { size='small' style={{ width: 300 }} /> - - - {isEnabled && ( } diff --git a/web/src/components/settings/oauth2/modals/JWKSInfoModal.jsx b/web/src/components/settings/oauth2/modals/JWKSInfoModal.jsx index 99c2eefc9..0c127b844 100644 --- a/web/src/components/settings/oauth2/modals/JWKSInfoModal.jsx +++ b/web/src/components/settings/oauth2/modals/JWKSInfoModal.jsx @@ -18,11 +18,10 @@ For commercial licensing, please contact support@quantumnous.com */ import React, { useState, useEffect } from 'react'; -import { Modal, Typography } from '@douyinfe/semi-ui'; +import { Modal } from '@douyinfe/semi-ui'; import { API, showError } from '../../../../helpers'; import { useTranslation } from 'react-i18next'; - -const { Text } = Typography; +import CodeViewer from '../../../common/ui/CodeViewer'; const JWKSInfoModal = ({ visible, onClose }) => { const { t } = useTranslation(); @@ -49,14 +48,7 @@ const JWKSInfoModal = ({ visible, onClose }) => { return ( - 🔐 - - {t('JWKS 信息')} - - - } + title={t('JWKS 信息')} visible={visible} onCancel={onClose} onOk={onClose} @@ -66,20 +58,11 @@ const JWKSInfoModal = ({ visible, onClose }) => { bodyStyle={{ padding: '20px 24px' }} confirmLoading={loading} > -
-        {jwksInfo ? JSON.stringify(jwksInfo, null, 2) : t('加载中...')}
-      
+
); }; diff --git a/web/src/components/settings/oauth2/modals/SecretDisplayModal.jsx b/web/src/components/settings/oauth2/modals/SecretDisplayModal.jsx index 815c0ad3a..10a5b2160 100644 --- a/web/src/components/settings/oauth2/modals/SecretDisplayModal.jsx +++ b/web/src/components/settings/oauth2/modals/SecretDisplayModal.jsx @@ -28,14 +28,7 @@ const SecretDisplayModal = ({ visible, onClose, secret }) => { return ( - 🔑 - - {t('客户端密钥已重新生成')} - - - } + title={t('客户端密钥已重新生成')} visible={visible} onCancel={onClose} onOk={onClose} @@ -45,29 +38,16 @@ const SecretDisplayModal = ({ visible, onClose, secret }) => { bodyStyle={{ padding: '20px 24px' }} > -
- - {secret} - -
-
- - 💡 {t('请妥善保管此密钥,用于应用程序的身份验证')} - -
+ + {secret} +
); }; diff --git a/web/src/components/settings/oauth2/modals/ServerInfoModal.jsx b/web/src/components/settings/oauth2/modals/ServerInfoModal.jsx index 3c52e6712..bd007492f 100644 --- a/web/src/components/settings/oauth2/modals/ServerInfoModal.jsx +++ b/web/src/components/settings/oauth2/modals/ServerInfoModal.jsx @@ -18,11 +18,10 @@ For commercial licensing, please contact support@quantumnous.com */ import React, { useState, useEffect } from 'react'; -import { Modal, Typography } from '@douyinfe/semi-ui'; +import { Modal } from '@douyinfe/semi-ui'; import { API, showError } from '../../../../helpers'; import { useTranslation } from 'react-i18next'; - -const { Text } = Typography; +import CodeViewer from '../../../common/ui/CodeViewer'; const ServerInfoModal = ({ visible, onClose }) => { const { t } = useTranslation(); @@ -49,14 +48,7 @@ const ServerInfoModal = ({ visible, onClose }) => { return ( - 🖥️ - - {t('OAuth2 服务器信息')} - - - } + title={t('OAuth2 服务器信息')} visible={visible} onCancel={onClose} onOk={onClose} @@ -66,20 +58,13 @@ const ServerInfoModal = ({ visible, onClose }) => { bodyStyle={{ padding: '20px 24px' }} confirmLoading={loading} > -
-        {serverInfo ? JSON.stringify(serverInfo, null, 2) : t('加载中...')}
-      
+
); }; diff --git a/web/src/components/settings/personal/cards/NotificationSettings.jsx b/web/src/components/settings/personal/cards/NotificationSettings.jsx index 0b097eaff..404945521 100644 --- a/web/src/components/settings/personal/cards/NotificationSettings.jsx +++ b/web/src/components/settings/personal/cards/NotificationSettings.jsx @@ -40,7 +40,7 @@ import { showSuccess, showError, } from '../../../../helpers'; -import CodeViewer from '../../../playground/CodeViewer'; +import CodeViewer from '../../../common/ui/CodeViewer'; import { StatusContext } from '../../../../context/Status'; import { UserContext } from '../../../../context/User'; import { useUserPermissions } from '../../../../hooks/common/useUserPermissions'; diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 0761ac4b7..1e95054a7 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -2174,5 +2174,8 @@ "生产环境务必启用 HTTPS,并妥善管理 JWT 签名密钥": "Enable HTTPS in production and manage JWT signing keys properly", "个客户端": "clients", "请妥善保管此密钥,用于应用程序的身份验证": "Please keep this secret safe, it is used for application authentication", - "客户端名称": "Client Name" + "客户端名称": "Client Name", + "暂无描述": "No description", + "OAuth2 服务器配置": "OAuth2 Server Configuration", + "JWKS 密钥集": "JWKS Key Set" }