v 0.1.3
parent
0ef036621c
commit
9ddeedf0b6
|
|
@ -10,6 +10,8 @@ import { BotDashboardModule } from './modules/dashboard/BotDashboardModule';
|
|||
import { pickLocale } from './i18n';
|
||||
import { appZhCn } from './i18n/app.zh-cn';
|
||||
import { appEn } from './i18n/app.en';
|
||||
import { LucentIconButton } from './components/lucent/LucentIconButton';
|
||||
import { LucentTooltip } from './components/lucent/LucentTooltip';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
|
|
@ -53,41 +55,45 @@ function App() {
|
|||
|
||||
<div className="global-switches">
|
||||
<div className="switch-compact">
|
||||
<LucentTooltip content={t.dark}>
|
||||
<button
|
||||
className={`switch-btn ${theme === 'dark' ? 'active' : ''}`}
|
||||
onClick={() => setTheme('dark')}
|
||||
title={t.dark}
|
||||
aria-label={t.dark}
|
||||
>
|
||||
<MoonStar size={14} />
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
<LucentTooltip content={t.light}>
|
||||
<button
|
||||
className={`switch-btn ${theme === 'light' ? 'active' : ''}`}
|
||||
onClick={() => setTheme('light')}
|
||||
title={t.light}
|
||||
aria-label={t.light}
|
||||
>
|
||||
<SunMedium size={14} />
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
</div>
|
||||
|
||||
<div className="switch-compact">
|
||||
<LucentTooltip content={t.zh}>
|
||||
<button
|
||||
className={`switch-btn switch-btn-lang ${locale === 'zh' ? 'active' : ''}`}
|
||||
onClick={() => setLocale('zh')}
|
||||
title={t.zh}
|
||||
aria-label={t.zh}
|
||||
>
|
||||
<span>ZH</span>
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
<LucentTooltip content={t.en}>
|
||||
<button
|
||||
className={`switch-btn switch-btn-lang ${locale === 'en' ? 'active' : ''}`}
|
||||
onClick={() => setLocale('en')}
|
||||
title={t.en}
|
||||
aria-label={t.en}
|
||||
>
|
||||
<span>EN</span>
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -111,9 +117,9 @@ function App() {
|
|||
<h3>{t.nav.images.title}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowImageFactory(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowImageFactory(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="app-modal-body">
|
||||
|
|
@ -131,9 +137,9 @@ function App() {
|
|||
<h3>{t.nav.onboarding.title}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowCreateWizard(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowCreateWizard(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="app-modal-body">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
||||
import { LucentTooltip } from './LucentTooltip';
|
||||
|
||||
interface LucentIconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title'> {
|
||||
tooltip?: string;
|
||||
tooltipSide?: 'top' | 'bottom';
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function LucentIconButton({
|
||||
tooltip,
|
||||
tooltipSide = 'top',
|
||||
children,
|
||||
'aria-label': ariaLabel,
|
||||
...buttonProps
|
||||
}: LucentIconButtonProps) {
|
||||
const tipText = String(tooltip || ariaLabel || '').trim();
|
||||
return (
|
||||
<LucentTooltip content={tipText} side={tooltipSide}>
|
||||
<button
|
||||
{...buttonProps}
|
||||
aria-label={String(ariaLabel || tipText || '').trim() || undefined}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { createContext, useCallback, useContext, useMemo, useRef, useState, type ReactNode } from 'react';
|
||||
import { AlertCircle, AlertTriangle, CheckCircle2, Info, X } from 'lucide-react';
|
||||
import { useAppStore } from '../../store/appStore';
|
||||
import { LucentIconButton } from './LucentIconButton';
|
||||
import './lucent-prompt.css';
|
||||
|
||||
type PromptTone = 'info' | 'success' | 'warning' | 'error';
|
||||
|
|
@ -133,14 +134,14 @@ export function LucentPromptProvider({ children }: { children: ReactNode }) {
|
|||
<div className="lucent-confirm-title">
|
||||
{confirmState.title || (locale === 'zh' ? '请确认操作' : 'Please Confirm')}
|
||||
</div>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="lucent-confirm-close"
|
||||
onClick={() => closeConfirm(false)}
|
||||
aria-label={locale === 'zh' ? '关闭' : 'Close'}
|
||||
title={locale === 'zh' ? '关闭' : 'Close'}
|
||||
tooltip={locale === 'zh' ? '关闭' : 'Close'}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
<div className="lucent-confirm-message">{confirmState.message}</div>
|
||||
<div className="lucent-confirm-actions">
|
||||
|
|
@ -165,4 +166,3 @@ export function useLucentPrompt() {
|
|||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,19 +21,40 @@
|
|||
visibility: hidden;
|
||||
transition: opacity 0.14s ease, transform 0.14s ease, visibility 0.14s ease;
|
||||
z-index: 40;
|
||||
box-shadow: 0 8px 18px rgba(6, 12, 24, 0.24);
|
||||
}
|
||||
|
||||
.lucent-tooltip-bubble::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-right: 1px solid color-mix(in oklab, var(--line) 72%, var(--brand) 28%);
|
||||
border-bottom: 1px solid color-mix(in oklab, var(--line) 72%, var(--brand) 28%);
|
||||
background: color-mix(in oklab, var(--panel) 88%, #000 12%);
|
||||
}
|
||||
|
||||
.lucent-tooltip-wrap.side-top .lucent-tooltip-bubble {
|
||||
bottom: calc(100% + 8px);
|
||||
}
|
||||
|
||||
.lucent-tooltip-wrap.side-top .lucent-tooltip-bubble::after {
|
||||
bottom: -5px;
|
||||
}
|
||||
|
||||
.lucent-tooltip-wrap.side-bottom .lucent-tooltip-bubble {
|
||||
top: calc(100% + 8px);
|
||||
}
|
||||
|
||||
.lucent-tooltip-wrap.side-bottom .lucent-tooltip-bubble::after {
|
||||
top: -5px;
|
||||
transform: translateX(-50%) rotate(225deg);
|
||||
}
|
||||
|
||||
.lucent-tooltip-wrap:hover .lucent-tooltip-bubble,
|
||||
.lucent-tooltip-wrap:focus-within .lucent-tooltip-bubble {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,19 +99,19 @@
|
|||
}
|
||||
|
||||
.ops-bot-icon-btn {
|
||||
width: 31px;
|
||||
height: 31px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
border-radius: 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ops-bot-icon-btn svg {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
stroke-width: 2.2;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
stroke-width: 2.1;
|
||||
}
|
||||
|
||||
.ops-bot-actions .ops-bot-action-monitor {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { pickLocale } from '../../i18n';
|
|||
import { dashboardZhCn } from '../../i18n/dashboard.zh-cn';
|
||||
import { dashboardEn } from '../../i18n/dashboard.en';
|
||||
import { useLucentPrompt } from '../../components/lucent/LucentPromptProvider';
|
||||
import { LucentTooltip } from '../../components/lucent/LucentTooltip';
|
||||
import { LucentIconButton } from '../../components/lucent/LucentIconButton';
|
||||
|
||||
interface BotDashboardModuleProps {
|
||||
onOpenCreateWizard?: () => void;
|
||||
|
|
@ -905,7 +905,7 @@ export function BotDashboardModule({
|
|||
<div className="ops-chat-meta-right">
|
||||
<span className="mono">{formatClock(item.ts)}</span>
|
||||
{collapsible ? (
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="ops-chat-expand-icon-btn"
|
||||
onClick={() =>
|
||||
setExpandedProgressByKey((prev) => ({
|
||||
|
|
@ -913,11 +913,11 @@ export function BotDashboardModule({
|
|||
[itemKey]: !prev[itemKey],
|
||||
}))
|
||||
}
|
||||
title={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
||||
tooltip={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
||||
aria-label={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
||||
>
|
||||
{expanded ? '×' : '…'}
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1994,22 +1994,22 @@ export function BotDashboardModule({
|
|||
<div className="row-between">
|
||||
<h2 style={{ fontSize: 18 }}>{t.titleBots}</h2>
|
||||
<div className="ops-list-actions">
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={onOpenImageFactory}
|
||||
title={t.manageImages}
|
||||
tooltip={t.manageImages}
|
||||
aria-label={t.manageImages}
|
||||
>
|
||||
<Boxes size={14} />
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-primary btn-sm icon-btn"
|
||||
onClick={onOpenCreateWizard}
|
||||
title={t.newBot}
|
||||
tooltip={t.newBot}
|
||||
aria-label={t.newBot}
|
||||
>
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2032,27 +2032,26 @@ export function BotDashboardModule({
|
|||
</div>
|
||||
<div className="ops-bot-meta">{t.image}: <span className="mono">{bot.image_tag || '-'}</span></div>
|
||||
<div className="ops-bot-actions">
|
||||
<LucentTooltip content={isZh ? '资源监测' : 'Resource Monitor'}>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-sm ops-bot-icon-btn ops-bot-action-monitor"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openResourceMonitor(bot.id);
|
||||
}}
|
||||
tooltip={isZh ? '资源监测' : 'Resource Monitor'}
|
||||
aria-label={isZh ? '资源监测' : 'Resource Monitor'}
|
||||
>
|
||||
<Gauge size={14} />
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
</LucentIconButton>
|
||||
{bot.docker_status === 'RUNNING' ? (
|
||||
<LucentTooltip content={t.stop}>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-sm ops-bot-icon-btn ops-bot-action-stop"
|
||||
disabled={isOperating}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
void stopBot(bot.id, bot.docker_status);
|
||||
}}
|
||||
tooltip={t.stop}
|
||||
aria-label={t.stop}
|
||||
>
|
||||
{isStopping ? (
|
||||
|
|
@ -2064,17 +2063,16 @@ export function BotDashboardModule({
|
|||
</span>
|
||||
</span>
|
||||
) : <Square size={14} />}
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
</LucentIconButton>
|
||||
) : (
|
||||
<LucentTooltip content={t.start}>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-sm ops-bot-icon-btn ops-bot-action-start"
|
||||
disabled={isOperating}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
void startBot(bot.id, bot.docker_status);
|
||||
}}
|
||||
tooltip={t.start}
|
||||
aria-label={t.start}
|
||||
>
|
||||
{isStarting ? (
|
||||
|
|
@ -2086,21 +2084,19 @@ export function BotDashboardModule({
|
|||
</span>
|
||||
</span>
|
||||
) : <Power size={14} />}
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
</LucentIconButton>
|
||||
)}
|
||||
<LucentTooltip content={t.delete}>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-sm ops-bot-icon-btn ops-bot-action-delete"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
void removeBot(bot.id);
|
||||
}}
|
||||
tooltip={t.delete}
|
||||
aria-label={t.delete}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentTooltip>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -2163,15 +2159,15 @@ export function BotDashboardModule({
|
|||
: t.disabledPlaceholder
|
||||
}
|
||||
/>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary icon-btn"
|
||||
disabled={!canChat || isUploadingAttachments}
|
||||
onClick={triggerPickAttachments}
|
||||
title={isUploadingAttachments ? t.uploadingFile : t.uploadFile}
|
||||
tooltip={isUploadingAttachments ? t.uploadingFile : t.uploadFile}
|
||||
aria-label={isUploadingAttachments ? t.uploadingFile : t.uploadFile}
|
||||
>
|
||||
<Paperclip size={14} className={isUploadingAttachments ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
disabled={!isChatEnabled || (!command.trim() && pendingAttachments.length === 0)}
|
||||
|
|
@ -2210,18 +2206,18 @@ export function BotDashboardModule({
|
|||
</a>
|
||||
);
|
||||
})()}
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="icon-btn ops-chip-remove"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setPendingAttachments((prev) => prev.filter((v) => v !== p));
|
||||
}}
|
||||
title={t.removeAttachment}
|
||||
tooltip={t.removeAttachment}
|
||||
aria-label={t.removeAttachment}
|
||||
>
|
||||
<X size={12} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -2254,24 +2250,24 @@ export function BotDashboardModule({
|
|||
<div className="row-between ops-runtime-head">
|
||||
<h2 style={{ fontSize: 18 }}>{t.runtime}</h2>
|
||||
<div className="ops-panel-tools" ref={runtimeMenuRef}>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setRuntimeViewMode((m) => (m === 'visual' ? 'text' : 'visual'))}
|
||||
title={runtimeViewMode === 'visual' ? (isZh ? '切换为文字面板' : 'Switch to text panel') : (isZh ? '切换为机器人面板' : 'Switch to bot panel')}
|
||||
tooltip={runtimeViewMode === 'visual' ? (isZh ? '切换为文字面板' : 'Switch to text panel') : (isZh ? '切换为机器人面板' : 'Switch to bot panel')}
|
||||
aria-label={runtimeViewMode === 'visual' ? (isZh ? '切换为文字面板' : 'Switch to text panel') : (isZh ? '切换为机器人面板' : 'Switch to bot panel')}
|
||||
>
|
||||
<Repeat2 size={14} />
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setRuntimeMenuOpen((v) => !v)}
|
||||
title={runtimeMoreLabel}
|
||||
tooltip={runtimeMoreLabel}
|
||||
aria-label={runtimeMoreLabel}
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={runtimeMenuOpen}
|
||||
>
|
||||
<EllipsisVertical size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
{runtimeMenuOpen ? (
|
||||
<div className="ops-more-menu" role="menu" aria-label={runtimeMoreLabel}>
|
||||
<button
|
||||
|
|
@ -2412,14 +2408,14 @@ export function BotDashboardModule({
|
|||
<div className="ops-runtime-action-inline">
|
||||
<strong className="ops-runtime-action-text">{runtimeActionDisplay}</strong>
|
||||
{runtimeActionHasMore ? (
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="ops-runtime-expand-btn"
|
||||
onClick={() => setShowRuntimeActionModal(true)}
|
||||
title={isZh ? '查看完整内容' : 'Show full content'}
|
||||
tooltip={isZh ? '查看完整内容' : 'Show full content'}
|
||||
aria-label={isZh ? '查看完整内容' : 'Show full content'}
|
||||
>
|
||||
…
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2433,15 +2429,15 @@ export function BotDashboardModule({
|
|||
<div className="section-mini-title">{t.workspaceOutputs}</div>
|
||||
{workspaceError ? <div className="ops-empty-inline">{workspaceError}</div> : null}
|
||||
<div className="workspace-toolbar">
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="workspace-refresh-icon-btn"
|
||||
disabled={workspaceLoading || !selectedBotId}
|
||||
onClick={() => void loadWorkspaceTree(selectedBot.id, workspaceCurrentPath)}
|
||||
title={lc.refreshHint}
|
||||
tooltip={lc.refreshHint}
|
||||
aria-label={lc.refreshHint}
|
||||
>
|
||||
<RefreshCw size={14} className={workspaceLoading ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
<label className="workspace-auto-switch" title={lc.autoRefresh}>
|
||||
<span className="workspace-auto-switch-label">{lc.autoRefresh}</span>
|
||||
<input
|
||||
|
|
@ -2487,14 +2483,14 @@ export function BotDashboardModule({
|
|||
</section>
|
||||
</div>
|
||||
{compactMode && isCompactMobile ? (
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="ops-compact-fab-switch"
|
||||
onClick={() => setCompactPanelTab((v) => (v === 'chat' ? 'runtime' : 'chat'))}
|
||||
title={compactPanelTab === 'chat' ? (isZh ? '切换到运行面板' : 'Switch to runtime') : (isZh ? '切换到对话面板' : 'Switch to chat')}
|
||||
tooltip={compactPanelTab === 'chat' ? (isZh ? '切换到运行面板' : 'Switch to runtime') : (isZh ? '切换到对话面板' : 'Switch to chat')}
|
||||
aria-label={compactPanelTab === 'chat' ? (isZh ? '切换到运行面板' : 'Switch to runtime') : (isZh ? '切换到对话面板' : 'Switch to chat')}
|
||||
>
|
||||
{compactPanelTab === 'chat' ? <Activity size={18} /> : <MessageSquareText size={18} />}
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
) : null}
|
||||
|
||||
{showResourceModal && (
|
||||
|
|
@ -2506,22 +2502,22 @@ export function BotDashboardModule({
|
|||
<span className="modal-sub mono">{resourceBot?.name || resourceBotId}</span>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => void loadResourceSnapshot(resourceBotId)}
|
||||
title={isZh ? '立即刷新' : 'Refresh now'}
|
||||
tooltip={isZh ? '立即刷新' : 'Refresh now'}
|
||||
aria-label={isZh ? '立即刷新' : 'Refresh now'}
|
||||
>
|
||||
<RefreshCw size={14} className={resourceLoading ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setShowResourceModal(false)}
|
||||
title={t.close}
|
||||
tooltip={t.close}
|
||||
aria-label={t.close}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2589,9 +2585,9 @@ export function BotDashboardModule({
|
|||
<span className="modal-sub">{t.baseConfigSub}</span>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowBaseModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowBaseModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2661,9 +2657,9 @@ export function BotDashboardModule({
|
|||
<h3>{t.modelParams}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowParamModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowParamModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="slider-row">
|
||||
|
|
@ -2743,9 +2739,9 @@ export function BotDashboardModule({
|
|||
<h3>{lc.wizardSectionTitle}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowChannelModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowChannelModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card" style={{ fontSize: 12, color: 'var(--muted)' }}>
|
||||
|
|
@ -2773,15 +2769,15 @@ export function BotDashboardModule({
|
|||
/>
|
||||
{lc.sendToolHints}
|
||||
</label>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-primary btn-sm icon-btn"
|
||||
disabled={isSavingGlobalDelivery || !selectedBot}
|
||||
onClick={() => void saveGlobalDelivery()}
|
||||
title={lc.saveChannel}
|
||||
tooltip={lc.saveChannel}
|
||||
aria-label={lc.saveChannel}
|
||||
>
|
||||
<Save size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="wizard-channel-list">
|
||||
|
|
@ -2801,28 +2797,29 @@ export function BotDashboardModule({
|
|||
/>
|
||||
{lc.enabled}
|
||||
</label>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm wizard-icon-btn"
|
||||
disabled={isDashboardChannel(channel) || isSavingChannel}
|
||||
onClick={() => void removeChannel(channel)}
|
||||
title={lc.remove}
|
||||
tooltip={lc.remove}
|
||||
aria-label={lc.remove}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
{renderChannelFields(channel, idx)}
|
||||
<div className="row-between">
|
||||
<span className="field-label">{lc.customChannel}</span>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-primary btn-sm icon-btn"
|
||||
disabled={isSavingChannel}
|
||||
onClick={() => void saveChannel(channel)}
|
||||
title={lc.saveChannel}
|
||||
tooltip={lc.saveChannel}
|
||||
aria-label={lc.saveChannel}
|
||||
>
|
||||
<Save size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -2840,15 +2837,15 @@ export function BotDashboardModule({
|
|||
<option key={t} value={t}>{t}</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
disabled={addableChannelTypes.length === 0 || isSavingChannel}
|
||||
onClick={() => void addChannel()}
|
||||
title={lc.addChannel}
|
||||
tooltip={lc.addChannel}
|
||||
aria-label={lc.addChannel}
|
||||
>
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2862,9 +2859,9 @@ export function BotDashboardModule({
|
|||
<h3>{t.skillsPanel}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowSkillsModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowSkillsModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="wizard-channel-list">
|
||||
|
|
@ -2880,13 +2877,14 @@ export function BotDashboardModule({
|
|||
<div className="field-label mono">{String(skill.type || '').toUpperCase()}</div>
|
||||
<div className="field-label">{skill.description || '-'}</div>
|
||||
</div>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm wizard-icon-btn"
|
||||
onClick={() => void removeBotSkill(skill)}
|
||||
title={t.removeSkill}
|
||||
tooltip={t.removeSkill}
|
||||
aria-label={t.removeSkill}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
|
@ -2927,9 +2925,9 @@ export function BotDashboardModule({
|
|||
<h3>{t.envParams}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowEnvParamsModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowEnvParamsModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field-label" style={{ marginBottom: 8 }}>{t.envParamsDesc}</div>
|
||||
|
|
@ -2948,21 +2946,22 @@ export function BotDashboardModule({
|
|||
onChange={(e) => upsertEnvParam(key, e.target.value)}
|
||||
placeholder={t.envValue}
|
||||
/>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm wizard-icon-btn"
|
||||
onClick={() => setEnvVisibleByKey((prev) => ({ ...prev, [key]: !prev[key] }))}
|
||||
title={envVisibleByKey[key] ? t.hideEnvValue : t.showEnvValue}
|
||||
tooltip={envVisibleByKey[key] ? t.hideEnvValue : t.showEnvValue}
|
||||
aria-label={envVisibleByKey[key] ? t.hideEnvValue : t.showEnvValue}
|
||||
>
|
||||
{envVisibleByKey[key] ? <EyeOff size={14} /> : <Eye size={14} />}
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm wizard-icon-btn"
|
||||
onClick={() => removeEnvParam(key)}
|
||||
title={t.removeEnvParam}
|
||||
tooltip={t.removeEnvParam}
|
||||
aria-label={t.removeEnvParam}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
|
@ -2983,15 +2982,15 @@ export function BotDashboardModule({
|
|||
onChange={(e) => setEnvDraftValue(e.target.value)}
|
||||
placeholder={t.envValue}
|
||||
/>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setEnvDraftVisible((v) => !v)}
|
||||
title={envDraftVisible ? t.hideEnvValue : t.showEnvValue}
|
||||
tooltip={envDraftVisible ? t.hideEnvValue : t.showEnvValue}
|
||||
aria-label={envDraftVisible ? t.hideEnvValue : t.showEnvValue}
|
||||
>
|
||||
{envDraftVisible ? <EyeOff size={14} /> : <Eye size={14} />}
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => {
|
||||
const key = String(envDraftKey || '').trim().toUpperCase();
|
||||
|
|
@ -3000,11 +2999,11 @@ export function BotDashboardModule({
|
|||
setEnvDraftKey('');
|
||||
setEnvDraftValue('');
|
||||
}}
|
||||
title={t.addEnvParam}
|
||||
tooltip={t.addEnvParam}
|
||||
aria-label={t.addEnvParam}
|
||||
>
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
<div className="row-between">
|
||||
<span className="field-label">{t.envParamsHint}</span>
|
||||
|
|
@ -3025,18 +3024,18 @@ export function BotDashboardModule({
|
|||
<h3>{t.cronViewer}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => selectedBot && void loadCronJobs(selectedBot.id)}
|
||||
title={t.cronReload}
|
||||
tooltip={t.cronReload}
|
||||
aria-label={t.cronReload}
|
||||
disabled={cronLoading}
|
||||
>
|
||||
<RefreshCw size={14} className={cronLoading ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowCronModal(false)} title={t.close} aria-label={t.close}>
|
||||
</LucentIconButton>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowCronModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
{cronLoading ? (
|
||||
|
|
@ -3067,24 +3066,24 @@ export function BotDashboardModule({
|
|||
<div className="ops-cron-meta">{job.enabled === false ? t.cronDisabled : t.cronEnabled}</div>
|
||||
</div>
|
||||
<div className="ops-cron-actions">
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm icon-btn"
|
||||
onClick={() => void stopCronJob(job.id)}
|
||||
title={t.cronStop}
|
||||
tooltip={t.cronStop}
|
||||
aria-label={t.cronStop}
|
||||
disabled={stopping || job.enabled === false}
|
||||
>
|
||||
<PowerOff size={13} />
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm icon-btn"
|
||||
onClick={() => void deleteCronJob(job.id)}
|
||||
title={t.cronDelete}
|
||||
tooltip={t.cronDelete}
|
||||
aria-label={t.cronDelete}
|
||||
disabled={stopping}
|
||||
>
|
||||
<Trash2 size={13} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -3103,9 +3102,9 @@ export function BotDashboardModule({
|
|||
<h3>{t.agentFiles}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowAgentModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowAgentModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="wizard-agent-layout">
|
||||
|
|
@ -3132,9 +3131,9 @@ export function BotDashboardModule({
|
|||
<h3>{t.lastAction}</h3>
|
||||
</div>
|
||||
<div className="modal-title-actions">
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowRuntimeActionModal(false)} title={t.close} aria-label={t.close}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowRuntimeActionModal(false)} tooltip={t.close} aria-label={t.close}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="workspace-preview-body">
|
||||
|
|
@ -3153,22 +3152,22 @@ export function BotDashboardModule({
|
|||
<span className="modal-sub mono">{workspacePreview.path}</span>
|
||||
</div>
|
||||
<div className="workspace-preview-header-actions">
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setWorkspacePreviewFullscreen((v) => !v)}
|
||||
title={workspacePreviewFullscreen ? (isZh ? '退出全屏' : 'Exit full screen') : (isZh ? '全屏预览' : 'Full screen')}
|
||||
tooltip={workspacePreviewFullscreen ? (isZh ? '退出全屏' : 'Exit full screen') : (isZh ? '全屏预览' : 'Full screen')}
|
||||
aria-label={workspacePreviewFullscreen ? (isZh ? '退出全屏' : 'Exit full screen') : (isZh ? '全屏预览' : 'Full screen')}
|
||||
>
|
||||
{workspacePreviewFullscreen ? <Minimize2 size={14} /> : <Maximize2 size={14} />}
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={closeWorkspacePreview}
|
||||
title={t.close}
|
||||
tooltip={t.close}
|
||||
aria-label={t.close}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`workspace-preview-body ${workspacePreview.isMarkdown ? 'markdown' : ''}`}>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { pickLocale } from '../../i18n';
|
|||
import { imageFactoryZhCn } from '../../i18n/image-factory.zh-cn';
|
||||
import { imageFactoryEn } from '../../i18n/image-factory.en';
|
||||
import { useLucentPrompt } from '../../components/lucent/LucentPromptProvider';
|
||||
import { LucentIconButton } from '../../components/lucent/LucentIconButton';
|
||||
|
||||
interface NanobotImage {
|
||||
tag: string;
|
||||
|
|
@ -178,15 +179,15 @@ export function ImageFactoryModule() {
|
|||
<td>{img.version}</td>
|
||||
<td><span className={statusClass(img.status)}>{img.status}</span></td>
|
||||
<td>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm icon-btn"
|
||||
disabled={isDeletingTag === img.tag}
|
||||
onClick={() => void handleDeleteRegistered(img.tag)}
|
||||
title={isDeletingTag === img.tag ? t.deleting : t.deleteRegistry}
|
||||
tooltip={isDeletingTag === img.tag ? t.deleting : t.deleteRegistry}
|
||||
aria-label={isDeletingTag === img.tag ? t.deleting : t.deleteRegistry}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
|
@ -202,14 +203,14 @@ export function ImageFactoryModule() {
|
|||
<h2>{t.dockerTitle}</h2>
|
||||
<p className="panel-desc">{t.dockerDesc}</p>
|
||||
</div>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary icon-btn"
|
||||
onClick={() => void refreshDockerImages()}
|
||||
title={isRefreshing ? t.refreshing : t.refresh}
|
||||
tooltip={isRefreshing ? t.refreshing : t.refresh}
|
||||
aria-label={isRefreshing ? t.refreshing : t.refresh}
|
||||
>
|
||||
<RefreshCw size={14} className={isRefreshing ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
|
||||
<div className="card" style={{ fontSize: 12, color: 'var(--muted)' }}>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { pickLocale } from '../../../i18n';
|
|||
import { managementZhCn } from '../../../i18n/management.zh-cn';
|
||||
import { managementEn } from '../../../i18n/management.en';
|
||||
import { useLucentPrompt } from '../../../components/lucent/LucentPromptProvider';
|
||||
import { LucentIconButton } from '../../../components/lucent/LucentIconButton';
|
||||
|
||||
interface KernelManagerModalProps {
|
||||
isOpen: boolean;
|
||||
|
|
@ -65,9 +66,9 @@ export function KernelManagerModal({ isOpen, onClose }: KernelManagerModalProps)
|
|||
<Cpu className="text-blue-400" size={24} />
|
||||
<h2 className="text-xl font-bold text-white">{t.title}</h2>
|
||||
</div>
|
||||
<button onClick={onClose} className="p-2 hover:bg-slate-700 rounded-full transition-colors text-white">
|
||||
<LucentIconButton onClick={onClose} className="p-2 hover:bg-slate-700 rounded-full transition-colors text-white" tooltip={locale === 'zh' ? '关闭' : 'Close'} aria-label={locale === 'zh' ? '关闭' : 'Close'}>
|
||||
<X size={20} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
|
||||
<div className="p-6">
|
||||
|
|
@ -87,13 +88,14 @@ export function KernelManagerModal({ isOpen, onClose }: KernelManagerModalProps)
|
|||
<span className={`text-[9px] font-bold ${img.status === 'READY' ? 'text-green-500' : 'text-slate-400'}`}>
|
||||
{img.status}
|
||||
</span>
|
||||
<button
|
||||
<LucentIconButton
|
||||
onClick={() => handleRemoveImage(img.tag)}
|
||||
className="ml-2 p-1.5 hover:bg-red-500/20 text-slate-500 hover:text-red-500 rounded transition-colors"
|
||||
title={t.removeRecord}
|
||||
tooltip={t.removeRecord}
|
||||
aria-label={t.removeRecord}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { pickLocale } from '../../i18n';
|
|||
import { wizardZhCn } from '../../i18n/wizard.zh-cn';
|
||||
import { wizardEn } from '../../i18n/wizard.en';
|
||||
import { useLucentPrompt } from '../../components/lucent/LucentPromptProvider';
|
||||
import { LucentIconButton } from '../../components/lucent/LucentIconButton';
|
||||
|
||||
type AgentTab = 'AGENTS' | 'SOUL' | 'USER' | 'TOOLS' | 'IDENTITY';
|
||||
type ChannelType = 'feishu' | 'qq' | 'dingtalk' | 'telegram' | 'slack';
|
||||
|
|
@ -698,9 +699,9 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
<div className="mono">
|
||||
{configuredChannelsLabel}
|
||||
</div>
|
||||
<button className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowChannelModal(true)} title={lc.openManager} aria-label={lc.openManager}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" onClick={() => setShowChannelModal(true)} tooltip={lc.openManager} aria-label={lc.openManager}>
|
||||
<Settings2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
|
||||
<div className="section-mini-title" style={{ marginTop: 6 }}>{ui.toolsConfig}</div>
|
||||
|
|
@ -709,14 +710,14 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
<div className="mono">
|
||||
{envEntries.length > 0 ? envEntries.map(([k]) => k).join(', ') : ui.noEnvParams}
|
||||
</div>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setShowToolsConfigModal(true)}
|
||||
title={ui.openToolsManager}
|
||||
tooltip={ui.openToolsManager}
|
||||
aria-label={ui.openToolsManager}
|
||||
>
|
||||
<Settings2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -825,13 +826,14 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
/>
|
||||
{lc.enabled}
|
||||
</label>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm wizard-icon-btn"
|
||||
onClick={() => removeChannel(idx)}
|
||||
title={lc.remove}
|
||||
tooltip={lc.remove}
|
||||
aria-label={lc.remove}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -846,9 +848,9 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
<option key={t} value={t}>{t}</option>
|
||||
))}
|
||||
</select>
|
||||
<button className="btn btn-secondary btn-sm icon-btn" disabled={addableChannelTypes.length === 0} onClick={addChannel} title={lc.addChannel} aria-label={lc.addChannel}>
|
||||
<LucentIconButton className="btn btn-secondary btn-sm icon-btn" disabled={addableChannelTypes.length === 0} onClick={addChannel} tooltip={lc.addChannel} aria-label={lc.addChannel}>
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
<div className="row-between">
|
||||
<span className="field-label">{lc.wizardSectionDesc}</span>
|
||||
|
|
@ -883,21 +885,22 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
onChange={(e) => upsertEnvParam(key, e.target.value)}
|
||||
placeholder={ui.envValue}
|
||||
/>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm wizard-icon-btn"
|
||||
onClick={() => setEnvVisibleByKey((prev) => ({ ...prev, [key]: !prev[key] }))}
|
||||
title={envVisibleByKey[key] ? ui.hideEnvValue : ui.showEnvValue}
|
||||
tooltip={envVisibleByKey[key] ? ui.hideEnvValue : ui.showEnvValue}
|
||||
aria-label={envVisibleByKey[key] ? ui.hideEnvValue : ui.showEnvValue}
|
||||
>
|
||||
{envVisibleByKey[key] ? <EyeOff size={14} /> : <Eye size={14} />}
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-danger btn-sm wizard-icon-btn"
|
||||
onClick={() => removeEnvParam(key)}
|
||||
title={ui.removeEnvParam}
|
||||
tooltip={ui.removeEnvParam}
|
||||
aria-label={ui.removeEnvParam}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
|
@ -917,15 +920,15 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
onChange={(e) => setEnvDraftValue(e.target.value)}
|
||||
placeholder={ui.envValue}
|
||||
/>
|
||||
<button
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => setEnvDraftVisible((v) => !v)}
|
||||
title={envDraftVisible ? ui.hideEnvValue : ui.showEnvValue}
|
||||
tooltip={envDraftVisible ? ui.hideEnvValue : ui.showEnvValue}
|
||||
aria-label={envDraftVisible ? ui.hideEnvValue : ui.showEnvValue}
|
||||
>
|
||||
{envDraftVisible ? <EyeOff size={14} /> : <Eye size={14} />}
|
||||
</button>
|
||||
<button
|
||||
</LucentIconButton>
|
||||
<LucentIconButton
|
||||
className="btn btn-secondary btn-sm icon-btn"
|
||||
onClick={() => {
|
||||
const key = String(envDraftKey || '').trim().toUpperCase();
|
||||
|
|
@ -934,11 +937,11 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
|
|||
setEnvDraftKey('');
|
||||
setEnvDraftValue('');
|
||||
}}
|
||||
title={ui.addEnvParam}
|
||||
tooltip={ui.addEnvParam}
|
||||
aria-label={ui.addEnvParam}
|
||||
>
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</LucentIconButton>
|
||||
</div>
|
||||
<div className="row-between">
|
||||
<span className="field-label">{ui.toolsDesc}</span>
|
||||
|
|
|
|||
Loading…
Reference in New Issue