Skip to content
Merged

Dev #65

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/api/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,6 @@ export async function getClassActivityByInstructorId(
return { data: [] };
}

console.log("Log data", JSON.stringify(logs, null, 2));

return { data: logs };
} catch (err) {
return {
Expand Down
16 changes: 11 additions & 5 deletions src/components/DownloadFormattedFile.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Download } from "lucide-react";
import { Download, Loader2 } from "lucide-react";
import { saveAs } from "file-saver";
import Papa from "papaparse";
import { Button } from "./ui/button";
Expand All @@ -9,6 +9,7 @@ interface DownloadFormattedFileProps {
data: any[];
filename?: string;
disabled?: boolean;
loading?: boolean;
}

/**
Expand All @@ -20,6 +21,7 @@ const DownloadFormattedFile = ({
data,
filename = "data",
disabled = false,
loading = false,
}: DownloadFormattedFileProps) => {
const [format, setFormat] = useState<"csv" | "json">("csv");

Expand Down Expand Up @@ -62,10 +64,14 @@ const DownloadFormattedFile = ({
border-0"
disabled={disabled}
>
<div className="flex items-center gap-2">
<Download className="w-4 h-4" />
<span>Download {format.toUpperCase()}</span>
</div>
{loading ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<div className="flex items-center gap-2">
<Download className="w-4 h-4" />
<span>Download {format.toUpperCase()}</span>
</div>
)}
</Button>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/TypingLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ const TypingLogs = ({ userId }: TypingLogsProps) => {
className="px-4 py-2 bg-primary text-primary-foreground rounded-lg disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed hover:bg-primary/90 transition-colors flex items-center gap-2"
>
<RefreshCw className="size-4" />
Reload All Records
<span className="hidden md:inline">Reload All Records</span>
</button>
</CardHeader>

Expand Down
63 changes: 56 additions & 7 deletions src/components/TypingLogsDownloadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,22 @@ type TypingLogData = {
correct_line: string | null;
incorrect_line: string | null;
shown_bug: boolean | null;
bug_percentage: number | null; // Add this field
bug_percentage: number | null;
line_suggestions_group?: {
filename: string | null;
language: string | null;
} | null;
} | null;
};

type TerminalLogData = {
id: string;
start_time: string;
end_time: string;
output: string;
user_id: string;
};

const TypingLogsDownloadButton = ({
userId,
user,
Expand All @@ -44,19 +52,52 @@ const TypingLogsDownloadButton = ({
"SUGGESTION_GENERATE",
];

// Function to find matching terminal output for a given timestamp
const findMatchingTerminalOutput = (
eventTimestamp: string,
terminalLogs: TerminalLogData[],
): string | null => {
const eventTime = new Date(eventTimestamp).getTime();

for (const terminalLog of terminalLogs) {
const startTime = new Date(terminalLog.start_time).getTime();
const endTime = new Date(terminalLog.end_time).getTime();

if (eventTime >= startTime && eventTime <= endTime) {
return terminalLog.output;
}
}

return null;
};

useEffect(() => {
const fetchTypingData = async () => {
if (!userId) return;

setLoading(true);

try {
// First, fetch terminal logs for the user
const { data: terminalLogsData, error: terminalLogsError } =
await supabase
.from("terminal_logs")
.select("id, start_time, end_time, output, user_id")
.eq("user_id", userId)
.order("start_time", { ascending: true });

if (terminalLogsError) {
throw terminalLogsError;
}

const terminalLogs = terminalLogsData as TerminalLogData[];

// Then fetch typing logs
const allLogs: TypingLogData[] = [];
let from = 0;
const batchSize = 1000;
let hasMoreData = true;

// Fetch all records in batches
while (hasMoreData) {
const { data, error } = await supabase
.from("typing_log")
Expand Down Expand Up @@ -93,11 +134,9 @@ const TypingLogsDownloadButton = ({
const logs = data as unknown as TypingLogData[];
allLogs.push(...logs);

// Check if we got a full batch, if not, we're done
hasMoreData = logs.length === batchSize;
from += batchSize;

// Add a small delay to prevent overwhelming the server
if (hasMoreData) {
await new Promise((resolve) => setTimeout(resolve, 50));
}
Expand All @@ -114,6 +153,12 @@ const TypingLogsDownloadButton = ({
timeDifference = currentTime - previousTime;
}

// Find matching terminal output
const terminalOutput = findMatchingTerminalOutput(
log.created_at,
terminalLogs,
);

return {
"No.": index + 1,
PID: user?.pid || "N/A",
Expand All @@ -125,11 +170,14 @@ const TypingLogsDownloadButton = ({
"Correct Line": log.line_suggestions?.correct_line || "N/A",
"Incorrect Line": log.line_suggestions?.incorrect_line || "N/A",
"Bug Shown": log.line_suggestions?.shown_bug ?? "N/A",
"Bug Percentage": log.line_suggestions?.bug_percentage ?? "N/A", // Changed this line
"Bug Percentage": log.line_suggestions?.bug_percentage ?? "N/A",
Filename:
log.line_suggestions?.line_suggestions_group?.filename || "N/A",
Language:
log.line_suggestions?.line_suggestions_group?.language || "N/A",
"Terminal Output": terminalOutput
? terminalOutput.replace(/\n/g, "\\n")
: "N/A",
};
}) || [];

Expand All @@ -142,7 +190,7 @@ const TypingLogsDownloadButton = ({
};

fetchTypingData();
}, [userId, user]); // Removed userSettings dependency
}, [userId, user]);

const filename = user?.pid
? `typing-logs-${user.firstName}-${user.pid}`
Expand All @@ -152,7 +200,8 @@ const TypingLogsDownloadButton = ({
<DownloadFormattedFile
data={typingData}
filename={filename}
disabled={loading || typingData.length === 0}
disabled={typingData.length === 0}
loading={loading}
/>
);
};
Expand Down
Loading