mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-10 13:10:57 +00:00
Fix/frontend optimizations (#2088)
* fix(web): auto-redirect to wizard on first visit and change sidebar icons to blue * refactor(wizard): use backend metadata table instead of localStorage for wizard completion state - Add wizard_completed field to system info API (read from metadata table) - Add POST /api/v1/system/wizard/completed endpoint to mark wizard done - Frontend home layout checks systemInfo.wizard_completed for auto-redirect - Wizard calls markWizardCompleted API on skip/finish - Ensures consistent behavior across all browsers on the same instance * fix(wizard): update systemInfo in memory before navigation to prevent redirect loop * fix(monitoring): prevent horizontal overflow and unify empty state styles * fix(wizard): use Object.assign for systemInfo and await wizard completion API - Replace systemInfo reassignment with Object.assign in all 3 locations to preserve object identity across module imports - Await markWizardCompleted() POST in wizard skip/finish handlers instead of fire-and-forget to ensure backend persistence - Always re-fetch systemInfo in home layout to get latest wizard_completed state from backend * fix(wizard): prevent redirect loop by blocking navigation on failed status save - Refactor wizard_completed (boolean) to wizard_status (string: none/skipped/completed) - Remove ALL localStorage usage from wizard page (form state persistence) - Replace AlertDialogAction with Button so skip dialog stays open during POST - Add loading spinners for skip and complete actions - If POST fails, show error toast and keep dialog/button active for retry - If POST succeeds, update in-memory state and navigate * fix(wizard): fix row[0].value bug causing GET /info to always return wizard_status=none conn.execute(select(Entity)) returns Row with raw column values, not ORM entities. row[0] is the key column (a string), so row[0].value raises AttributeError which was silently swallowed by except-pass, making the GET endpoint always return wizard_status=none regardless of DB state. * fix(wizard): replace AlertDialog with Dialog for skip confirmation to remove slide animation * chore: optimize toast in wizard * fix(wizard): set default token value for Telegram adapter and initialize adapter config in wizard * feat(web): move webhook URL to dynamic form system, add market category filter, fix layout overflow - Add 'webhook-url' dynamic form field type rendered as read-only input with copy button, defined in adapter YAML specs instead of hardcoded in BotForm. Supports show_if conditions for optional-webhook adapters. - Remove hardcoded webhook display logic from BotForm.tsx, pass webhook URLs via systemContext to DynamicFormComponent. - Fetch webhook URLs after bot creation in wizard and pass to Step 1. - Support ?category= query param on /home/market page for filtering by component type (mirrors langbot-space behavior). - Link 'install knowledge engine' hint to /home/market?category=KnowledgeEngine. - Fix SidebarInset missing min-w-0 causing content overflow when sidebar is expanded. - Add vertical divider between plugin detail config and readme panels. - Fix infinite re-render loop in DynamicFormComponent by memoizing editableItems array. * fix: lint * fix(web): change systemInfo to const to satisfy prefer-const lint rule * fix: update adapter descriptions for clarity and usage requirements
This commit is contained in:
@@ -701,6 +701,10 @@ export class BackendClient extends BaseHttpClient {
|
||||
return this.get('/api/v1/system/info');
|
||||
}
|
||||
|
||||
public updateWizardStatus(status: 'skipped' | 'completed'): Promise<void> {
|
||||
return this.post('/api/v1/system/wizard/completed', { status });
|
||||
}
|
||||
|
||||
public getAsyncTasks(): Promise<ApiRespAsyncTasks> {
|
||||
return this.get('/api/v1/system/tasks');
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CloudServiceClient } from './CloudServiceClient';
|
||||
import { ApiRespSystemInfo } from '@/app/infra/entities/api';
|
||||
|
||||
// 系统信息
|
||||
export let systemInfo: ApiRespSystemInfo = {
|
||||
export const systemInfo: ApiRespSystemInfo = {
|
||||
debug: false,
|
||||
version: '',
|
||||
edition: 'community',
|
||||
@@ -16,6 +16,7 @@ export let systemInfo: ApiRespSystemInfo = {
|
||||
max_pipelines: -1,
|
||||
max_extensions: -1,
|
||||
},
|
||||
wizard_status: 'none',
|
||||
};
|
||||
|
||||
// 用户信息
|
||||
@@ -50,7 +51,7 @@ if (typeof window !== 'undefined' && systemInfo.cloud_service_url === '') {
|
||||
backendClient
|
||||
.getSystemInfo()
|
||||
.then((info) => {
|
||||
systemInfo = info;
|
||||
Object.assign(systemInfo, info);
|
||||
cloudServiceClient.updateBaseURL(info.cloud_service_url);
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -65,7 +66,7 @@ if (typeof window !== 'undefined' && systemInfo.cloud_service_url === '') {
|
||||
export const getCloudServiceClient = async (): Promise<CloudServiceClient> => {
|
||||
if (systemInfo.cloud_service_url === '') {
|
||||
try {
|
||||
systemInfo = await backendClient.getSystemInfo();
|
||||
Object.assign(systemInfo, await backendClient.getSystemInfo());
|
||||
// 更新 cloud service client 的 baseURL
|
||||
cloudServiceClient.updateBaseURL(systemInfo.cloud_service_url);
|
||||
} catch (error) {
|
||||
@@ -90,7 +91,7 @@ export const getCloudServiceClientSync = (): CloudServiceClient => {
|
||||
*/
|
||||
export const initializeSystemInfo = async (): Promise<void> => {
|
||||
try {
|
||||
systemInfo = await backendClient.getSystemInfo();
|
||||
Object.assign(systemInfo, await backendClient.getSystemInfo());
|
||||
cloudServiceClient.updateBaseURL(systemInfo.cloud_service_url);
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize system info:', error);
|
||||
|
||||
Reference in New Issue
Block a user