mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-24 21:36:06 +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:
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback, useRef, Suspense } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import {
|
||||
Select,
|
||||
@@ -46,9 +47,24 @@ function MarketPageContent({
|
||||
installPlugin: (plugin: PluginV4) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const validCategories = [
|
||||
'Tool',
|
||||
'Command',
|
||||
'EventListener',
|
||||
'KnowledgeEngine',
|
||||
'Parser',
|
||||
];
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [componentFilter, setComponentFilter] = useState<string>('all');
|
||||
const [componentFilter, setComponentFilter] = useState<string>(() => {
|
||||
const category = searchParams.get('category');
|
||||
if (category && validCategories.includes(category)) {
|
||||
return category;
|
||||
}
|
||||
return 'all';
|
||||
});
|
||||
const [selectedTags, setSelectedTags] = useState<string[]>([]);
|
||||
const [availableTags, setAvailableTags] = useState<PluginTag[]>([]);
|
||||
const [tagNames, setTagNames] = useState<Record<string, string>>({});
|
||||
@@ -284,6 +300,18 @@ function MarketPageContent({
|
||||
setComponentFilter(value);
|
||||
setCurrentPage(1);
|
||||
setPlugins([]);
|
||||
|
||||
// Update URL query param to keep it in sync
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (value === 'all') {
|
||||
params.delete('category');
|
||||
} else {
|
||||
params.set('category', value);
|
||||
}
|
||||
const newUrl = params.toString()
|
||||
? `${window.location.pathname}?${params.toString()}`
|
||||
: window.location.pathname;
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
// fetchPlugins will be called by useEffect when componentFilter changes
|
||||
}, []);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user