Skip to content

Commit

Permalink
[OPIK-297] [FE] Implement csv export in the traces table (#463)
Browse files Browse the repository at this point in the history
  • Loading branch information
andriidudar authored Oct 23, 2024
1 parent fce1c79 commit d545dba
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
42 changes: 42 additions & 0 deletions apps/opik-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/opik-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@
"date-fns": "^3.6.0",
"dayjs": "^1.11.11",
"diff": "^7.0.0",
"file-saver": "^2.0.5",
"flattie": "^1.1.1",
"js-yaml": "^4.1.0",
"json-2-csv": "^5.5.6",
"lodash": "^4.17.21",
"lucide-react": "^0.395.0",
"md5": "^2.3.0",
Expand All @@ -90,6 +92,7 @@
"@tanstack/router-vite-plugin": "^1.37.0",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^14.3.1",
"@types/file-saver": "^2.0.7",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.5",
"@types/node": "^20.14.13",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React, { useCallback, useRef, useState } from "react";
import { Database, Trash } from "lucide-react";
import last from "lodash/last";
import get from "lodash/get";
import { json2csv } from "json-2-csv";
import FileSaver from "file-saver";
import { ArrowDownToLine, Database, Trash } from "lucide-react";

import {
DropdownMenu,
Expand All @@ -17,25 +21,43 @@ import useTracesBatchDeleteMutation from "@/api/traces/useTraceBatchDeleteMutati
type TracesActionsButtonProps = {
type: TRACE_DATA_TYPE;
rows: Array<Trace | Span>;
selectedColumns: string[];
projectId: string;
};

const TracesActionsButton: React.FunctionComponent<
TracesActionsButtonProps
> = ({ rows, type, projectId }) => {
> = ({ rows, type, selectedColumns, projectId }) => {
const resetKeyRef = useRef(0);
const [open, setOpen] = useState<boolean | number>(false);

const tracesBatchDeleteMutation = useTracesBatchDeleteMutation();

const deleteTraces = useCallback(() => {
const deleteTracesHandler = useCallback(() => {
tracesBatchDeleteMutation.mutate({
projectId,
ids: rows.map((row) => row.id),
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [projectId, rows]);

const exportCSVHandler = useCallback(() => {
const mappedRows = rows.map((row) => {
return selectedColumns.reduce<Record<string, unknown>>((acc, column) => {
// we need split by dot to parse usage into correct structure
const keys = column.split(".");
const key = last(keys) as string;
acc[key] = get(row, keys, "");
return acc;
}, {});
});

FileSaver.saveAs(
new Blob([json2csv(mappedRows)], { type: "text/csv;charset=utf-8" }),
type === TRACE_DATA_TYPE.traces ? "traces.csv" : "llm_calls.csv",
);
}, [rows, selectedColumns, type]);

return (
<>
<AddToDatasetDialog
Expand All @@ -48,7 +70,7 @@ const TracesActionsButton: React.FunctionComponent<
key={`delete-${resetKeyRef.current}`}
open={open === 2}
setOpen={setOpen}
onConfirm={deleteTraces}
onConfirm={deleteTracesHandler}
title="Delete traces"
description="Are you sure you want to delete all selected traces?"
confirmText="Delete traces"
Expand Down Expand Up @@ -80,6 +102,13 @@ const TracesActionsButton: React.FunctionComponent<
Delete
</DropdownMenuItem>
)}
<DropdownMenuItem
onClick={exportCSVHandler}
disabled={selectedColumns.length === 0}
>
<ArrowDownToLine className="mr-2 size-4" />
Export CSV
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ const TracesPage = () => {
<TracesActionsButton
projectId={projectId}
rows={selectedRows}
selectedColumns={selectedColumns}
type={type as TRACE_DATA_TYPE}
/>
)}
Expand Down

0 comments on commit d545dba

Please sign in to comment.