mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-04-30 09:21:33 +00:00
refactor: remove loading sessions logic from sidebar
This commit is contained in:
@@ -19,7 +19,6 @@ import { getConnectableHost } from '../shared/networkHosts.js';
|
||||
|
||||
import { findAppRoot, getModuleDir } from './utils/runtime-paths.js';
|
||||
import {
|
||||
getSessionsById,
|
||||
renameProjectById,
|
||||
deleteSessionById,
|
||||
deleteProjectById,
|
||||
@@ -76,7 +75,7 @@ import pluginsRoutes from './routes/plugins.js';
|
||||
import messagesRoutes from './routes/messages.js';
|
||||
import providerRoutes from './modules/providers/provider.routes.js';
|
||||
import { startEnabledPluginServers, stopAllPlugins, getPluginPort } from './utils/plugin-process-manager.js';
|
||||
import { initializeDatabase, sessionsDb, applyCustomSessionNames } from './modules/database/index.js';
|
||||
import { initializeDatabase, sessionsDb } from './modules/database/index.js';
|
||||
import { configureWebPush } from './services/vapid-keys.js';
|
||||
import { validateApiKey, authenticateToken, authenticateWebSocket } from './middleware/auth.js';
|
||||
import { IS_PLATFORM } from './constants/config.js';
|
||||
@@ -303,18 +302,6 @@ app.post('/api/system/update', authenticateToken, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Sessions for a project; `projectId` is resolved to a path via the DB.
|
||||
app.get('/api/projects/:projectId/sessions', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const { limit = 5, offset = 0 } = req.query;
|
||||
const result = await getSessionsById(req.params.projectId, parseInt(limit), parseInt(offset));
|
||||
applyCustomSessionNames(result.sessions, 'claude');
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Rename project endpoint; stores the custom name on the DB row for `projectId`.
|
||||
app.put('/api/projects/:projectId/rename', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
|
||||
@@ -666,26 +666,6 @@ async function getSessionMessages(projectName, sessionId, limit = null, offset =
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ID-based wrapper around `getSessions`.
|
||||
*
|
||||
* Resolves a `projectId` to the underlying Claude JSONL folder name (via the
|
||||
* DB-backed project path) and defers to the legacy filesystem reader. Keeps
|
||||
* the previous pagination shape so the sidebar's "Load more sessions" UI keeps
|
||||
* working after the migration.
|
||||
*/
|
||||
async function getSessionsById(projectId, limit = 5, offset = 0) {
|
||||
const projectPath = await getProjectPathById(projectId);
|
||||
if (!projectPath) {
|
||||
return { sessions: [], hasMore: false, total: 0 };
|
||||
}
|
||||
|
||||
// Claude stores history under ~/.claude/projects/<encoded-path>/; derive the
|
||||
// folder name from the absolute path the DB gave us.
|
||||
const claudeFolderName = claudeFolderNameFromPath(projectPath);
|
||||
return getSessions(claudeFolderName, limit, offset);
|
||||
}
|
||||
|
||||
// Rename a project's display name
|
||||
async function renameProject(projectName, newDisplayName) {
|
||||
const config = await loadProjectConfig();
|
||||
@@ -2053,7 +2033,6 @@ async function getGeminiCliSessionMessages(sessionId) {
|
||||
// based helpers (`getSessions`, `renameProject`, `deleteSession`, etc.) are
|
||||
// kept as internal implementation details of the id-based wrappers below.
|
||||
export {
|
||||
getSessionsById,
|
||||
getSessionMessages,
|
||||
renameProjectById,
|
||||
deleteSessionById,
|
||||
|
||||
@@ -4,9 +4,7 @@ import type { TFunction } from 'i18next';
|
||||
import { api } from '../../../utils/api';
|
||||
import type { Project, ProjectSession, LLMProvider } from '../../../types/app';
|
||||
import type {
|
||||
AdditionalSessionsByProject,
|
||||
DeleteProjectConfirmation,
|
||||
LoadingSessionsByProject,
|
||||
ProjectSortOrder,
|
||||
SessionDeleteConfirmation,
|
||||
SessionWithProvider,
|
||||
@@ -99,13 +97,10 @@ export function useSidebarController({
|
||||
const [editingProject, setEditingProject] = useState<string | null>(null);
|
||||
const [showNewProject, setShowNewProject] = useState(false);
|
||||
const [editingName, setEditingName] = useState('');
|
||||
const [loadingSessions, setLoadingSessions] = useState<LoadingSessionsByProject>({});
|
||||
const [additionalSessions, setAdditionalSessions] = useState<AdditionalSessionsByProject>({});
|
||||
const [initialSessionsLoaded, setInitialSessionsLoaded] = useState<Set<string>>(new Set());
|
||||
const [currentTime, setCurrentTime] = useState(new Date());
|
||||
const [projectSortOrder, setProjectSortOrder] = useState<ProjectSortOrder>('name');
|
||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||
const [projectHasMoreOverrides, setProjectHasMoreOverrides] = useState<Record<string, boolean>>({});
|
||||
const [editingSession, setEditingSession] = useState<string | null>(null);
|
||||
const [editingSessionName, setEditingSessionName] = useState('');
|
||||
const [searchFilter, setSearchFilter] = useState('');
|
||||
@@ -133,9 +128,7 @@ export function useSidebarController({
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setAdditionalSessions({});
|
||||
setInitialSessionsLoaded(new Set());
|
||||
setProjectHasMoreOverrides({});
|
||||
}, [projects]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -342,31 +335,11 @@ export function useSidebarController({
|
||||
[starredProjects],
|
||||
);
|
||||
|
||||
const getProjectSessions = useCallback(
|
||||
(project: Project) => getAllSessions(project, additionalSessions),
|
||||
[additionalSessions],
|
||||
);
|
||||
|
||||
const projectsWithSessionMeta = useMemo(
|
||||
() =>
|
||||
projects.map((project) => {
|
||||
// The `hasMore` override map is keyed by projectId (see loadMoreSessions).
|
||||
const hasMoreOverride = projectHasMoreOverrides[project.projectId];
|
||||
if (hasMoreOverride === undefined) {
|
||||
return project;
|
||||
}
|
||||
|
||||
return {
|
||||
...project,
|
||||
sessionMeta: { ...project.sessionMeta, hasMore: hasMoreOverride },
|
||||
};
|
||||
}),
|
||||
[projectHasMoreOverrides, projects],
|
||||
);
|
||||
const getProjectSessions = useCallback((project: Project) => getAllSessions(project), []);
|
||||
|
||||
const sortedProjects = useMemo(
|
||||
() => sortProjects(projectsWithSessionMeta, projectSortOrder, starredProjects, additionalSessions),
|
||||
[additionalSessions, projectSortOrder, projectsWithSessionMeta, starredProjects],
|
||||
() => sortProjects(projects, projectSortOrder, starredProjects),
|
||||
[projectSortOrder, projects, starredProjects],
|
||||
);
|
||||
|
||||
const filteredProjects = useMemo(
|
||||
@@ -504,51 +477,6 @@ export function useSidebarController({
|
||||
}
|
||||
}, [deleteConfirmation, onProjectDelete, t]);
|
||||
|
||||
const loadMoreSessions = useCallback(
|
||||
async (project: Project) => {
|
||||
// Per-project bookkeeping (additionalSessions, loadingSessions,
|
||||
// projectHasMoreOverrides) is indexed by the DB `projectId`.
|
||||
const hasMoreOverride = projectHasMoreOverrides[project.projectId];
|
||||
const canLoadMore =
|
||||
hasMoreOverride !== undefined ? hasMoreOverride : project.sessionMeta?.hasMore === true;
|
||||
if (!canLoadMore || loadingSessions[project.projectId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
setLoadingSessions((prev) => ({ ...prev, [project.projectId]: true }));
|
||||
|
||||
try {
|
||||
const currentSessionCount =
|
||||
(project.sessions?.length || 0) + (additionalSessions[project.projectId]?.length || 0);
|
||||
const response = await api.sessions(project.projectId, 5, currentSessionCount);
|
||||
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = (await response.json()) as {
|
||||
sessions?: ProjectSession[];
|
||||
hasMore?: boolean;
|
||||
};
|
||||
|
||||
setAdditionalSessions((prev) => ({
|
||||
...prev,
|
||||
[project.projectId]: [...(prev[project.projectId] || []), ...(result.sessions || [])],
|
||||
}));
|
||||
|
||||
if (result.hasMore === false) {
|
||||
// Keep hasMore state in local hook state instead of mutating the project prop object.
|
||||
setProjectHasMoreOverrides((prev) => ({ ...prev, [project.projectId]: false }));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading more sessions:', error);
|
||||
} finally {
|
||||
setLoadingSessions((prev) => ({ ...prev, [project.projectId]: false }));
|
||||
}
|
||||
},
|
||||
[additionalSessions, loadingSessions, projectHasMoreOverrides],
|
||||
);
|
||||
|
||||
const handleProjectSelect = useCallback(
|
||||
(project: Project) => {
|
||||
onProjectSelect(project);
|
||||
@@ -609,8 +537,6 @@ export function useSidebarController({
|
||||
editingProject,
|
||||
showNewProject,
|
||||
editingName,
|
||||
loadingSessions,
|
||||
additionalSessions,
|
||||
initialSessionsLoaded,
|
||||
currentTime,
|
||||
projectSortOrder,
|
||||
@@ -636,7 +562,6 @@ export function useSidebarController({
|
||||
confirmDeleteSession,
|
||||
requestProjectDelete,
|
||||
confirmDeleteProject,
|
||||
loadMoreSessions,
|
||||
handleProjectSelect,
|
||||
refreshProjects,
|
||||
updateSessionSummary,
|
||||
|
||||
@@ -6,9 +6,6 @@ export type SessionWithProvider = ProjectSession & {
|
||||
__provider: LLMProvider;
|
||||
};
|
||||
|
||||
export type AdditionalSessionsByProject = Record<string, ProjectSession[]>;
|
||||
export type LoadingSessionsByProject = Record<string, boolean>;
|
||||
|
||||
export type DeleteProjectConfirmation = {
|
||||
project: Project;
|
||||
sessionCount: number;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { Project } from '../../../types/app';
|
||||
import type {
|
||||
AdditionalSessionsByProject,
|
||||
ProjectSortOrder,
|
||||
SettingsProject,
|
||||
SessionViewModel,
|
||||
SessionWithProvider,
|
||||
} from '../types/types';
|
||||
import type { ProjectSortOrder, SettingsProject, SessionViewModel, SessionWithProvider } from '../types/types';
|
||||
|
||||
export const readProjectSortOrder = (): ProjectSortOrder => {
|
||||
try {
|
||||
@@ -98,16 +92,11 @@ export const createSessionViewModel = (
|
||||
};
|
||||
};
|
||||
|
||||
export const getAllSessions = (
|
||||
project: Project,
|
||||
additionalSessions: AdditionalSessionsByProject,
|
||||
): SessionWithProvider[] => {
|
||||
// `additionalSessions` is indexed by DB `projectId` now (the sidebar keys
|
||||
// every per-project map by the same identifier).
|
||||
const claudeSessions = [
|
||||
...(project.sessions || []),
|
||||
...(additionalSessions[project.projectId] || []),
|
||||
].map((session) => ({ ...session, __provider: 'claude' as const }));
|
||||
export const getAllSessions = (project: Project): SessionWithProvider[] => {
|
||||
const claudeSessions = [...(project.sessions || [])].map((session) => ({
|
||||
...session,
|
||||
__provider: 'claude' as const,
|
||||
}));
|
||||
|
||||
const cursorSessions = (project.cursorSessions || []).map((session) => ({
|
||||
...session,
|
||||
@@ -129,11 +118,8 @@ export const getAllSessions = (
|
||||
);
|
||||
};
|
||||
|
||||
export const getProjectLastActivity = (
|
||||
project: Project,
|
||||
additionalSessions: AdditionalSessionsByProject,
|
||||
): Date => {
|
||||
const sessions = getAllSessions(project, additionalSessions);
|
||||
export const getProjectLastActivity = (project: Project): Date => {
|
||||
const sessions = getAllSessions(project);
|
||||
if (sessions.length === 0) {
|
||||
return new Date(0);
|
||||
}
|
||||
@@ -148,7 +134,6 @@ export const sortProjects = (
|
||||
projects: Project[],
|
||||
projectSortOrder: ProjectSortOrder,
|
||||
starredProjects: Set<string>,
|
||||
additionalSessions: AdditionalSessionsByProject,
|
||||
): Project[] => {
|
||||
const byName = [...projects];
|
||||
|
||||
@@ -166,10 +151,7 @@ export const sortProjects = (
|
||||
}
|
||||
|
||||
if (projectSortOrder === 'date') {
|
||||
return (
|
||||
getProjectLastActivity(projectB, additionalSessions).getTime() -
|
||||
getProjectLastActivity(projectA, additionalSessions).getTime()
|
||||
);
|
||||
return getProjectLastActivity(projectB).getTime() - getProjectLastActivity(projectA).getTime();
|
||||
}
|
||||
|
||||
return (projectA.displayName || projectA.projectId).localeCompare(projectB.displayName || projectB.projectId);
|
||||
|
||||
@@ -53,7 +53,6 @@ function Sidebar({
|
||||
editingProject,
|
||||
showNewProject,
|
||||
editingName,
|
||||
loadingSessions,
|
||||
initialSessionsLoaded,
|
||||
currentTime,
|
||||
isRefreshing,
|
||||
@@ -83,7 +82,6 @@ function Sidebar({
|
||||
confirmDeleteSession,
|
||||
requestProjectDelete,
|
||||
confirmDeleteProject,
|
||||
loadMoreSessions,
|
||||
handleProjectSelect,
|
||||
refreshProjects,
|
||||
updateSessionSummary,
|
||||
@@ -142,7 +140,6 @@ function Sidebar({
|
||||
expandedProjects,
|
||||
editingProject,
|
||||
editingName,
|
||||
loadingSessions,
|
||||
initialSessionsLoaded,
|
||||
currentTime,
|
||||
editingSession,
|
||||
@@ -164,9 +161,6 @@ function Sidebar({
|
||||
onDeleteProject: requestProjectDelete,
|
||||
onSessionSelect: handleSessionClick,
|
||||
onDeleteSession: showDeleteSessionConfirmation,
|
||||
onLoadMoreSessions: (project) => {
|
||||
void loadMoreSessions(project);
|
||||
},
|
||||
onNewSession,
|
||||
onEditingSessionNameChange: setEditingSessionName,
|
||||
onStartEditingSession: (sessionId, initialName) => {
|
||||
|
||||
@@ -19,7 +19,6 @@ type SidebarProjectItemProps = {
|
||||
editingName: string;
|
||||
sessions: SessionWithProvider[];
|
||||
initialSessionsLoaded: boolean;
|
||||
isLoadingSessions: boolean;
|
||||
currentTime: Date;
|
||||
editingSession: string | null;
|
||||
editingSessionName: string;
|
||||
@@ -40,7 +39,6 @@ type SidebarProjectItemProps = {
|
||||
sessionTitle: string,
|
||||
provider: LLMProvider,
|
||||
) => void;
|
||||
onLoadMoreSessions: (project: Project) => void;
|
||||
onNewSession: (project: Project) => void;
|
||||
onEditingSessionNameChange: (value: string) => void;
|
||||
onStartEditingSession: (sessionId: string, initialName: string) => void;
|
||||
@@ -49,14 +47,7 @@ type SidebarProjectItemProps = {
|
||||
t: TFunction;
|
||||
};
|
||||
|
||||
const getSessionCountDisplay = (sessions: SessionWithProvider[], hasMoreSessions: boolean): string => {
|
||||
const sessionCount = sessions.length;
|
||||
if (hasMoreSessions && sessionCount >= 5) {
|
||||
return `${sessionCount}+`;
|
||||
}
|
||||
|
||||
return `${sessionCount}`;
|
||||
};
|
||||
const getSessionCountDisplay = (sessions: SessionWithProvider[]): string => String(sessions.length);
|
||||
|
||||
export default function SidebarProjectItem({
|
||||
project,
|
||||
@@ -69,7 +60,6 @@ export default function SidebarProjectItem({
|
||||
editingName,
|
||||
sessions,
|
||||
initialSessionsLoaded,
|
||||
isLoadingSessions,
|
||||
currentTime,
|
||||
editingSession,
|
||||
editingSessionName,
|
||||
@@ -85,7 +75,6 @@ export default function SidebarProjectItem({
|
||||
onDeleteProject,
|
||||
onSessionSelect,
|
||||
onDeleteSession,
|
||||
onLoadMoreSessions,
|
||||
onNewSession,
|
||||
onEditingSessionNameChange,
|
||||
onStartEditingSession,
|
||||
@@ -97,8 +86,7 @@ export default function SidebarProjectItem({
|
||||
// after the projectName → projectId migration.
|
||||
const isSelected = selectedProject?.projectId === project.projectId;
|
||||
const isEditing = editingProject === project.projectId;
|
||||
const hasMoreSessions = project.sessionMeta?.hasMore === true;
|
||||
const sessionCountDisplay = getSessionCountDisplay(sessions, hasMoreSessions);
|
||||
const sessionCountDisplay = getSessionCountDisplay(sessions);
|
||||
const sessionCountLabel = `${sessionCountDisplay} session${sessions.length === 1 ? '' : 's'}`;
|
||||
const taskStatus = getTaskIndicatorStatus(project, mcpServerStatus);
|
||||
|
||||
@@ -411,7 +399,6 @@ export default function SidebarProjectItem({
|
||||
sessions={sessions}
|
||||
selectedSession={selectedSession}
|
||||
initialSessionsLoaded={initialSessionsLoaded}
|
||||
isLoadingSessions={isLoadingSessions}
|
||||
currentTime={currentTime}
|
||||
editingSession={editingSession}
|
||||
editingSessionName={editingSessionName}
|
||||
@@ -422,7 +409,6 @@ export default function SidebarProjectItem({
|
||||
onProjectSelect={onProjectSelect}
|
||||
onSessionSelect={onSessionSelect}
|
||||
onDeleteSession={onDeleteSession}
|
||||
onLoadMoreSessions={onLoadMoreSessions}
|
||||
onNewSession={onNewSession}
|
||||
t={t}
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { LoadingProgress, Project, ProjectSession, LLMProvider } from '../../../../types/app';
|
||||
import type {
|
||||
LoadingSessionsByProject,
|
||||
MCPServerStatus,
|
||||
SessionWithProvider,
|
||||
} from '../../types/types';
|
||||
import type { MCPServerStatus, SessionWithProvider } from '../../types/types';
|
||||
import SidebarProjectItem from './SidebarProjectItem';
|
||||
import SidebarProjectsState from './SidebarProjectsState';
|
||||
|
||||
@@ -19,7 +15,6 @@ export type SidebarProjectListProps = {
|
||||
expandedProjects: Set<string>;
|
||||
editingProject: string | null;
|
||||
editingName: string;
|
||||
loadingSessions: LoadingSessionsByProject;
|
||||
initialSessionsLoaded: Set<string>;
|
||||
currentTime: Date;
|
||||
editingSession: string | null;
|
||||
@@ -44,7 +39,6 @@ export type SidebarProjectListProps = {
|
||||
sessionTitle: string,
|
||||
provider: LLMProvider,
|
||||
) => void;
|
||||
onLoadMoreSessions: (project: Project) => void;
|
||||
onNewSession: (project: Project) => void;
|
||||
onEditingSessionNameChange: (value: string) => void;
|
||||
onStartEditingSession: (sessionId: string, initialName: string) => void;
|
||||
@@ -63,7 +57,6 @@ export default function SidebarProjectList({
|
||||
expandedProjects,
|
||||
editingProject,
|
||||
editingName,
|
||||
loadingSessions,
|
||||
initialSessionsLoaded,
|
||||
currentTime,
|
||||
editingSession,
|
||||
@@ -83,7 +76,6 @@ export default function SidebarProjectList({
|
||||
onDeleteProject,
|
||||
onSessionSelect,
|
||||
onDeleteSession,
|
||||
onLoadMoreSessions,
|
||||
onNewSession,
|
||||
onEditingSessionNameChange,
|
||||
onStartEditingSession,
|
||||
@@ -131,7 +123,6 @@ export default function SidebarProjectList({
|
||||
editingName={editingName}
|
||||
sessions={getProjectSessions(project)}
|
||||
initialSessionsLoaded={initialSessionsLoaded.has(project.projectId)}
|
||||
isLoadingSessions={Boolean(loadingSessions[project.projectId])}
|
||||
currentTime={currentTime}
|
||||
editingSession={editingSession}
|
||||
editingSessionName={editingSessionName}
|
||||
@@ -147,7 +138,6 @@ export default function SidebarProjectList({
|
||||
onDeleteProject={onDeleteProject}
|
||||
onSessionSelect={onSessionSelect}
|
||||
onDeleteSession={onDeleteSession}
|
||||
onLoadMoreSessions={onLoadMoreSessions}
|
||||
onNewSession={onNewSession}
|
||||
onEditingSessionNameChange={onEditingSessionNameChange}
|
||||
onStartEditingSession={onStartEditingSession}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChevronDown, Plus } from 'lucide-react';
|
||||
import { Plus } from 'lucide-react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { Button } from '../../../../shared/view/ui';
|
||||
import type { Project, ProjectSession, LLMProvider } from '../../../../types/app';
|
||||
@@ -11,7 +11,6 @@ type SidebarProjectSessionsProps = {
|
||||
sessions: SessionWithProvider[];
|
||||
selectedSession: ProjectSession | null;
|
||||
initialSessionsLoaded: boolean;
|
||||
isLoadingSessions: boolean;
|
||||
currentTime: Date;
|
||||
editingSession: string | null;
|
||||
editingSessionName: string;
|
||||
@@ -27,7 +26,6 @@ type SidebarProjectSessionsProps = {
|
||||
sessionTitle: string,
|
||||
provider: LLMProvider,
|
||||
) => void;
|
||||
onLoadMoreSessions: (project: Project) => void;
|
||||
onNewSession: (project: Project) => void;
|
||||
t: TFunction;
|
||||
};
|
||||
@@ -56,7 +54,6 @@ export default function SidebarProjectSessions({
|
||||
sessions,
|
||||
selectedSession,
|
||||
initialSessionsLoaded,
|
||||
isLoadingSessions,
|
||||
currentTime,
|
||||
editingSession,
|
||||
editingSessionName,
|
||||
@@ -67,7 +64,6 @@ export default function SidebarProjectSessions({
|
||||
onProjectSelect,
|
||||
onSessionSelect,
|
||||
onDeleteSession,
|
||||
onLoadMoreSessions,
|
||||
onNewSession,
|
||||
t,
|
||||
}: SidebarProjectSessionsProps) {
|
||||
@@ -76,7 +72,6 @@ export default function SidebarProjectSessions({
|
||||
}
|
||||
|
||||
const hasSessions = sessions.length > 0;
|
||||
const hasMoreSessions = project.sessionMeta?.hasMore === true;
|
||||
|
||||
return (
|
||||
<div className="ml-3 space-y-1 border-l border-border pl-3">
|
||||
@@ -105,7 +100,7 @@ export default function SidebarProjectSessions({
|
||||
|
||||
{!initialSessionsLoaded ? (
|
||||
<SessionListSkeleton />
|
||||
) : !hasSessions && !isLoadingSessions ? (
|
||||
) : !hasSessions ? (
|
||||
<div className="px-3 py-2 text-left">
|
||||
<p className="text-xs text-muted-foreground">{t('sessions.noSessions')}</p>
|
||||
</div>
|
||||
@@ -130,28 +125,6 @@ export default function SidebarProjectSessions({
|
||||
/>
|
||||
))
|
||||
)}
|
||||
|
||||
{hasSessions && hasMoreSessions && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="mt-2 w-full justify-center gap-2 text-muted-foreground"
|
||||
onClick={() => onLoadMoreSessions(project)}
|
||||
disabled={isLoadingSessions}
|
||||
>
|
||||
{isLoadingSessions ? (
|
||||
<>
|
||||
<div className="h-3 w-3 animate-spin rounded-full border border-muted-foreground border-t-transparent" />
|
||||
{t('sessions.loading')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
{t('sessions.showMore')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@ export const api = {
|
||||
projects: () => authenticatedFetch('/api/projects'),
|
||||
projectTaskmaster: (projectId) =>
|
||||
authenticatedFetch(`/api/projects/${encodeURIComponent(projectId)}/taskmaster`),
|
||||
sessions: (projectId, limit = 5, offset = 0) =>
|
||||
authenticatedFetch(`/api/projects/${projectId}/sessions?limit=${limit}&offset=${offset}`),
|
||||
// Unified endpoint — all providers through one URL. The legacy `projectName`
|
||||
// query parameter is preserved on the wire (routes/messages.js still reads
|
||||
// it) but it now carries a projectId value supplied by the caller.
|
||||
|
||||
Reference in New Issue
Block a user