mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-28 20:36:42 +08:00
feat: add beta environment banner
Add beta environment warning banner for Cloud beta deployments with i18n support (zh/en/ja)
This commit is contained in:
@@ -200,11 +200,22 @@ class SystemRouterGroup(group.RouterGroup):
|
||||
if invitation_delivery_service is None:
|
||||
invitation_delivery_service = InvitationDeliveryService(self.ap)
|
||||
|
||||
# Detect beta flag from telemetry diagnostics manager
|
||||
is_beta = False
|
||||
diagnostics = getattr(self.ap, 'diagnostics', None)
|
||||
if diagnostics is not None:
|
||||
is_beta = getattr(diagnostics, 'beta', False)
|
||||
|
||||
# Detect Cloud deployment mode
|
||||
is_cloud = getattr(getattr(self.ap, 'deployment', None), 'mode', 'oss') == 'cloud'
|
||||
|
||||
return self.success(
|
||||
data={
|
||||
'version': constants.semantic_version,
|
||||
'debug': constants.debug_mode,
|
||||
'edition': constants.edition,
|
||||
'beta': is_beta,
|
||||
'deployment_mode': 'cloud' if is_cloud else 'oss',
|
||||
'enable_marketplace': self.ap.instance_config.data.get('plugin', {}).get(
|
||||
'enable_marketplace', True
|
||||
),
|
||||
|
||||
Generated
+2113
-427
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,15 @@
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
import { BetaBanner } from '@/components/BetaBanner';
|
||||
|
||||
// Top-level route layout: drives the dynamic document title from the active
|
||||
// route and renders the matched child route via <Outlet />.
|
||||
export default function RootLayout() {
|
||||
useDocumentTitle();
|
||||
return <Outlet />;
|
||||
return (
|
||||
<>
|
||||
<BetaBanner />
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -566,6 +566,8 @@ export interface ApiRespSystemInfo {
|
||||
debug: boolean;
|
||||
version: string;
|
||||
edition: string;
|
||||
beta: boolean;
|
||||
deployment_mode: 'cloud' | 'oss';
|
||||
/** Independent instance-level gate for local stdio MCP transports. */
|
||||
mcp_stdio_enabled: boolean;
|
||||
cloud_service_url: string;
|
||||
|
||||
@@ -25,6 +25,8 @@ export const systemInfo: ApiRespSystemInfo = {
|
||||
debug: false,
|
||||
version: '',
|
||||
edition: 'community',
|
||||
beta: false,
|
||||
deployment_mode: 'oss',
|
||||
mcp_stdio_enabled: false,
|
||||
enable_marketplace: true,
|
||||
cloud_service_url: '',
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AlertCircle, X } from 'lucide-react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { backendClient } from '@/app/infra/http';
|
||||
|
||||
export function BetaBanner() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const [show, setShow] = useState(false);
|
||||
const [dismissed, setDismissed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkBetaStatus = async () => {
|
||||
try {
|
||||
const info = await backendClient.getSystemInfo();
|
||||
const shouldShow =
|
||||
info.deployment_mode === 'cloud' && info.beta === true;
|
||||
setShow(shouldShow);
|
||||
} catch {
|
||||
setShow(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkBetaStatus();
|
||||
}, []);
|
||||
|
||||
if (!show || dismissed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cloudUrl =
|
||||
i18n.language === 'zh-Hans' || i18n.language === 'zh_CN'
|
||||
? 'https://langbot.app/zh/cloud'
|
||||
: i18n.language === 'ja' || i18n.language === 'ja_JP'
|
||||
? 'https://langbot.app/ja/cloud'
|
||||
: 'https://langbot.app/cloud';
|
||||
|
||||
const ossUrl =
|
||||
i18n.language === 'zh-Hans' || i18n.language === 'zh_CN'
|
||||
? 'https://langbot.app/zh/docs/quick-start/deploy'
|
||||
: i18n.language === 'ja' || i18n.language === 'ja_JP'
|
||||
? 'https://langbot.app/ja/docs/quick-start/deploy'
|
||||
: 'https://langbot.app/docs/quick-start/deploy';
|
||||
|
||||
return (
|
||||
<Alert className="rounded-none border-x-0 border-t-0 bg-amber-50 dark:bg-amber-950/20 border-amber-200 dark:border-amber-900/50 py-2">
|
||||
<div className="flex items-start gap-3">
|
||||
<AlertCircle className="h-4 w-4 mt-0.5 text-amber-600 dark:text-amber-500 shrink-0" />
|
||||
<AlertDescription className="text-sm text-amber-900 dark:text-amber-100 flex-1">
|
||||
{t('beta_banner.message')}{' '}
|
||||
<a
|
||||
href={cloudUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline hover:text-amber-700 dark:hover:text-amber-300 font-medium"
|
||||
>
|
||||
{t('beta_banner.cloud_link')}
|
||||
</a>{' '}
|
||||
{t('beta_banner.or')}{' '}
|
||||
<a
|
||||
href={ossUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline hover:text-amber-700 dark:hover:text-amber-300 font-medium"
|
||||
>
|
||||
{t('beta_banner.oss_link')}
|
||||
</a>
|
||||
{t('beta_banner.period')}
|
||||
</AlertDescription>
|
||||
<button
|
||||
onClick={() => setDismissed(true)}
|
||||
className="shrink-0 text-amber-600 dark:text-amber-500 hover:text-amber-800 dark:hover:text-amber-300 p-1 -mt-1 -mr-2"
|
||||
aria-label={t('beta_banner.dismiss')}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
@@ -3313,5 +3313,14 @@ const enUS = {
|
||||
selectFromSidebar: 'Select a plugin page from the sidebar',
|
||||
invalidPage: 'Invalid plugin page',
|
||||
},
|
||||
beta_banner: {
|
||||
message:
|
||||
'This environment is in Beta testing. Service stability is not guaranteed. Consider using',
|
||||
cloud_link: 'LangBot Cloud (dedicated environment)',
|
||||
or: 'or',
|
||||
oss_link: 'self-hosted open-source version',
|
||||
period: '.',
|
||||
dismiss: 'Dismiss',
|
||||
},
|
||||
};
|
||||
export default enUS;
|
||||
|
||||
@@ -3327,5 +3327,13 @@ const jaJP = {
|
||||
selectFromSidebar: 'サイドバーからプラグインページを選択してください',
|
||||
invalidPage: '無効なプラグインページ',
|
||||
},
|
||||
beta_banner: {
|
||||
message: 'この環境はベータテスト中です。サービスの安定性は保証されません。',
|
||||
cloud_link: 'LangBot Cloud(専用環境)',
|
||||
or: 'または',
|
||||
oss_link: 'セルフホスト版',
|
||||
period: 'をご検討ください。',
|
||||
dismiss: '閉じる',
|
||||
},
|
||||
};
|
||||
export default jaJP;
|
||||
|
||||
@@ -3123,5 +3123,13 @@ const zhHans = {
|
||||
selectFromSidebar: '从侧边栏选择一个插件页面',
|
||||
invalidPage: '无效的插件页面',
|
||||
},
|
||||
beta_banner: {
|
||||
message: '当前环境正在进行 Beta 测试,服务稳定性不受保证,建议优先选择',
|
||||
cloud_link: '独立环境版 LangBot Cloud',
|
||||
or: '或',
|
||||
oss_link: '自部署开源版本',
|
||||
period: '。',
|
||||
dismiss: '关闭横幅',
|
||||
},
|
||||
};
|
||||
export default zhHans;
|
||||
|
||||
Reference in New Issue
Block a user