Skip to content

Commit

Permalink
WIP on loading problems via route
Browse files Browse the repository at this point in the history
  • Loading branch information
bhackett1024 committed Jan 17, 2025
1 parent 9e79118 commit b051425
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 61 deletions.
106 changes: 56 additions & 50 deletions app/components/chat/LoadProblemButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,58 @@ interface LoadProblemButtonProps {
importChat?: (description: string, messages: Message[]) => Promise<void>;
}

export async function loadProblem(problemId: string) {
let problem: BoltProblem | null = null;
try {
const rv = await sendCommandDedicatedClient({
method: "Recording.globalExperimentalCommand",
params: {
name: "fetchBoltProblem",
params: { problemId },
},
});
console.log("FetchProblemRval", rv);
problem = (rv as any).rval.problem;
} catch (error) {
console.error("Error fetching problem", error);
toast.error("Failed to fetch problem");
}

if (!problem) {
return;
}

console.log("Problem", problem);

const zip = new JSZip();
await zip.loadAsync(problem.prompt.content, { base64: true });

const fileArtifacts: FileArtifact[] = [];
for (const [key, object] of Object.entries(zip.files)) {
if (object.dir) continue;
fileArtifacts.push({
content: await object.async('text'),
path: key,
});
}

try {
const messages = await createChatFromFolder(fileArtifacts, [], "problem");

logStore.logSystem('Problem loaded successfully', {
problemId,
textFileCount: fileArtifacts.length,
});
toast.success('Problem loaded successfully');

return messages;
} catch (error) {
logStore.logError('Failed to load problem', error);
console.error('Failed to load problem:', error);
toast.error('Failed to load problem');
}
}

export const LoadProblemButton: React.FC<LoadProblemButtonProps> = ({ className, importChat }) => {
const [isLoading, setIsLoading] = useState(false);
const [isInputOpen, setIsInputOpen] = useState(false);
Expand All @@ -22,59 +74,13 @@ export const LoadProblemButton: React.FC<LoadProblemButtonProps> = ({ className,

const problemId = (document.getElementById('problem-input') as HTMLInputElement)?.value;

let problem: BoltProblem | null = null;
try {
const rv = await sendCommandDedicatedClient({
method: "Recording.globalExperimentalCommand",
params: {
name: "fetchBoltProblem",
params: { problemId },
},
});
console.log("FetchProblemRval", rv);
problem = (rv as any).rval.problem;
} catch (error) {
console.error("Error fetching problem", error);
toast.error("Failed to fetch problem");
}
const messages = await loadProblem(problemId);

if (!problem) {
return;
if (importChat) {
await importChat("Imported problem", messages ?? []);
}

console.log("Problem", problem);

const zip = new JSZip();
await zip.loadAsync(problem.prompt.content, { base64: true });

const fileArtifacts: FileArtifact[] = [];
for (const [key, object] of Object.entries(zip.files)) {
if (object.dir) continue;
fileArtifacts.push({
content: await object.async('text'),
path: key,
});
}

try {
const messages = await createChatFromFolder(fileArtifacts, [], "problem");

if (importChat) {
await importChat("Imported problem", [...messages]);
}

logStore.logSystem('Problem loaded successfully', {
problemId,
textFileCount: fileArtifacts.length,
});
toast.success('Problem loaded successfully');
} catch (error) {
logStore.logError('Failed to load problem', error);
console.error('Failed to load problem:', error);
toast.error('Failed to load problem');
} finally {
setIsLoading(false);
}
setIsLoading(false);
};

return (
Expand Down
7 changes: 5 additions & 2 deletions app/lib/persistence/useChatHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
duplicateChat,
createChatFromMessages,
} from './db';
import { loadProblem } from '~/components/chat/LoadProblemButton';

export interface ChatHistoryItem {
id: string;
Expand All @@ -32,7 +33,7 @@ export const description = atom<string | undefined>(undefined);

export function useChatHistory() {
const navigate = useNavigate();
const { id: mixedId } = useLoaderData<{ id?: string }>() ?? {};
const { id: mixedId, problemId } = useLoaderData<{ id?: string, problemId?: string }>() ?? {};
const [searchParams] = useSearchParams();

const [initialMessages, setInitialMessages] = useState<Message[]>([]);
Expand Down Expand Up @@ -75,11 +76,13 @@ export function useChatHistory() {
logStore.logError('Failed to load chat messages', error);
toast.error(error.message);
});
} else if (problemId) {
loadProblem(problemId).then(() => setReady(true));
}
}, []);

return {
ready: !mixedId || ready,
ready: ready || (!mixedId && !problemId),
initialMessages,
storeMessageHistory: async (messages: Message[]) => {
if (!db || messages.length === 0) {
Expand Down
8 changes: 8 additions & 0 deletions app/routes/problem.$id.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { json, type LoaderFunctionArgs } from '@remix-run/cloudflare';
import { default as IndexRoute } from './_index';

export async function loader(args: LoaderFunctionArgs) {
return json({ problemId: args.params.id });
}

export default IndexRoute;
19 changes: 10 additions & 9 deletions app/routes/problems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useEffect } from 'react';
import { useState } from 'react';

interface BoltProblemDescription {
id: string;
problemId: string;
title: string;
description: string;
timestamp: number;
Expand Down Expand Up @@ -87,20 +87,21 @@ function ProblemsPage() {
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-white"></div>
</div>
) : problems.length === 0 ? (
<div className="text-center text-gray-400">No problems found</div>
<div className="text-center text-gray-600">No problems found</div>
) : (
<div className="grid gap-4">
{problems.map((problem) => (
<div
key={problem.id}
className="p-4 rounded-lg bg-bolt-elements-background-depth-2"
<a
href={`/problem/${problem.problemId}`}
key={problem.problemId}
className="p-4 rounded-lg bg-bolt-elements-background-depth-2 hover:bg-bolt-elements-background-depth-3 transition-colors cursor-pointer"
>
<h2 className="text-xl font-semibold mb-2">{problem.title}</h2>
<p className="text-gray-300 mb-2">{problem.description}</p>
<p className="text-sm text-gray-400">
Time: {problem.timestamp}ms
<p className="text-gray-700 mb-2">{problem.description}</p>
<p className="text-sm text-gray-600">
Time: {new Date(problem.timestamp).toLocaleString()}
</p>
</div>
</a>
))}
</div>
)}
Expand Down

0 comments on commit b051425

Please sign in to comment.