forked from hangshuo652/aurak
feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params) - Add findByTemplateId method to service - Add GET /by-template/:templateId endpoint to controller - Service already includes CRUD for QuestionBank and QuestionBankItem
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
import './index.css';
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||
import { AuthProvider, useAuth } from './src/contexts/AuthContext';
|
||||
import { LanguageProvider } from './contexts/LanguageContext';
|
||||
import { ToastProvider } from './contexts/ToastContext';
|
||||
import { ConfirmProvider } from './contexts/ConfirmContext';
|
||||
import Login from './src/pages/auth/Login';
|
||||
import WorkspaceLayout from './src/components/layouts/WorkspaceLayout';
|
||||
|
||||
// Lazy-loaded page components
|
||||
const ChatPage = lazy(() => import('./src/pages/workspace/ChatPage'));
|
||||
const AgentsPage = lazy(() => import('./src/pages/workspace/AgentsPage'));
|
||||
const AssessmentPage = lazy(() => import('./src/pages/workspace/AssessmentPage'));
|
||||
const PluginsPage = lazy(() => import('./src/pages/workspace/PluginsPage'));
|
||||
const KnowledgePage = lazy(() => import('./src/pages/workspace/KnowledgePage'));
|
||||
const NotebooksPage = lazy(() => import('./src/pages/workspace/NotebooksPage'));
|
||||
const MemosPage = lazy(() => import('./src/pages/workspace/MemosPage'));
|
||||
const SettingsPage = lazy(() => import('./src/pages/workspace/SettingsPage'));
|
||||
const AssessmentStatsPage = lazy(() => import('./src/pages/workspace/AssessmentStatsPage'));
|
||||
|
||||
const PageLoader = () => (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin" />
|
||||
</div>
|
||||
);
|
||||
|
||||
function ProtectedRoute({ children, allowedRoles }: { children: React.ReactNode, allowedRoles?: string[] }) {
|
||||
const { user, isLoading } = useAuth();
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex h-screen items-center justify-center bg-slate-50">
|
||||
<PageLoader />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!user) return <Navigate to="/login" replace />;
|
||||
if (allowedRoles && !allowedRoles.includes(user.role)) return <Navigate to="/" replace />;
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function OverviewPage() {
|
||||
const { user } = useAuth();
|
||||
return (
|
||||
<div className="p-8 bg-white rounded-2xl shadow-sm border border-slate-100">
|
||||
<h1 className="text-2xl font-bold text-slate-900">Welcome back 👋</h1>
|
||||
<p className="mt-2 text-slate-500">
|
||||
Signed in as <span className="font-semibold">{user?.displayName || user?.username}</span>{' '}
|
||||
· role <span className="font-semibold text-blue-600">{user?.role?.replace(/_/g, ' ')}</span>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<LanguageProvider>
|
||||
<ToastProvider>
|
||||
<ConfirmProvider>
|
||||
<AuthProvider>
|
||||
<BrowserRouter>
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="flex h-screen items-center justify-center bg-slate-50">
|
||||
<PageLoader />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Routes>
|
||||
{/* Public */}
|
||||
<Route path="/login" element={<Login />} />
|
||||
|
||||
{/* Workspace */}
|
||||
<Route
|
||||
path="/*"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<WorkspaceLayout />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
>
|
||||
<Route index element={<OverviewPage />} />
|
||||
<Route path="chat" element={<ChatPage />} />
|
||||
<Route path="agents" element={<AgentsPage />} />
|
||||
<Route path="assessment" element={<AssessmentPage />} />
|
||||
<Route path="assessment-stats" element={<AssessmentStatsPage />} />
|
||||
<Route path="plugins" element={<PluginsPage />} />
|
||||
<Route path="notebook" element={<MemosPage />} />
|
||||
<Route path="knowledge/*" element={<KnowledgePage />} />
|
||||
<Route path="settings" element={<SettingsPage />} />
|
||||
<Route path="users" element={<SettingsPage initialTab="user" />} />
|
||||
<Route path="models" element={<SettingsPage initialTab="model" />} />
|
||||
<Route path="kb-settings" element={<SettingsPage initialTab="knowledge_base" />} />
|
||||
<Route path="tenants" element={<ProtectedRoute allowedRoles={['SUPER_ADMIN']}><SettingsPage initialTab="tenants" /></ProtectedRoute>} />
|
||||
</Route>
|
||||
|
||||
{/* Remove standalone Admin routes as we integrated Dashboard into Settings */}
|
||||
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</BrowserRouter>
|
||||
</AuthProvider>
|
||||
</ConfirmProvider>
|
||||
</ToastProvider>
|
||||
</LanguageProvider>
|
||||
);
|
||||
}
|
||||
|
||||
// ── Mount ──────────────────────────────────────────────────────────────────────
|
||||
const container = document.getElementById('root')!;
|
||||
createRoot(container).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
Reference in New Issue
Block a user