Skip to content

Commit 05c41c3

Browse files
committed
Add ExportButton component for exporting data to PDF and JSON
1 parent 4a33c0b commit 05c41c3

File tree

2 files changed

+94
-50
lines changed

2 files changed

+94
-50
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { UseReactToPrintFn } from 'react-to-print';
2+
import {
3+
DropdownMenu,
4+
DropdownMenuContent,
5+
DropdownMenuItem,
6+
DropdownMenuTrigger,
7+
} from '../ui/dropdown-menu';
8+
import { Button } from '../ui/button';
9+
import { ChevronDown, Share } from 'lucide-react';
10+
import { useTranslation } from 'react-i18next';
11+
import { ClusterInfo } from '../bias-detection-interfaces/cluster-export';
12+
import { CSVData } from '../bias-detection-interfaces/csv-data';
13+
import { downloadFile } from '@/lib/download-file';
14+
15+
export const ExportButton = ({
16+
clusterInfo,
17+
reactToPrintFn,
18+
data,
19+
buttonAlign,
20+
}: {
21+
buttonAlign: 'left' | 'right' | 'center';
22+
clusterInfo: ClusterInfo | undefined;
23+
reactToPrintFn: UseReactToPrintFn;
24+
data: CSVData;
25+
}) => {
26+
const { t } = useTranslation();
27+
const buttonAlignClass =
28+
buttonAlign === 'left'
29+
? 'mr-auto'
30+
: buttonAlign === 'right'
31+
? 'ml-auto'
32+
: 'mx-auto';
33+
return (
34+
<DropdownMenu>
35+
<DropdownMenuTrigger asChild>
36+
<Button
37+
variant="outline"
38+
size="sm"
39+
className={`${buttonAlignClass} p-4 text-sm`}
40+
>
41+
{t('downloadButton')}
42+
<ChevronDown
43+
className={`relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180`}
44+
/>
45+
</Button>
46+
</DropdownMenuTrigger>
47+
<DropdownMenuContent align="end">
48+
<DropdownMenuItem onClick={() => reactToPrintFn()}>
49+
<Share className="size-3.5 mr-2" />
50+
{t('biasSettings.exportToPDF')}
51+
</DropdownMenuItem>
52+
{clusterInfo && (
53+
<DropdownMenuItem
54+
onClick={() => {
55+
downloadFile(
56+
JSON.stringify(
57+
{
58+
fileName: data.fileName,
59+
...clusterInfo,
60+
},
61+
null,
62+
2
63+
),
64+
`${data.fileName.replace('.csv', '') || 'cluster-info'}-${clusterInfo.date.toISOString()}.json`,
65+
'application/json'
66+
);
67+
}}
68+
>
69+
<Share className="size-3.5 mr-2" />
70+
{t('biasSettings.exportToJSON')}
71+
</DropdownMenuItem>
72+
)}
73+
</DropdownMenuContent>
74+
</DropdownMenu>
75+
);
76+
};

src/routes/BiasDetection.tsx

Lines changed: 18 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,19 @@
1-
import { Button } from '@/components/ui/button';
21
import { useEffect, useRef, useState } from 'react';
32
import { pythonCode } from '@/assets/bias-detection-python-code';
43
import { usePython } from '@/components/pyodide/use-python';
54
import BiasSettings from '@/components/BiasSettings';
6-
import { ChevronDown, Share } from 'lucide-react';
75
import { csvReader } from '@/components/CSVReader';
86
import { cn } from '@/lib/utils';
97
import ComponentMapper from '@/components/componentMapper';
10-
import { downloadFile } from '@/lib/download-file';
118
import { useReactToPrint } from 'react-to-print';
129
import Measuring from '@/components/icons/measuring.svg?react';
1310
import { ClusterInfo } from '@/components/bias-detection-interfaces/cluster-export';
1411
import { BiasDetectionParameters } from '@/components/bias-detection-interfaces/BiasDetectionParameters';
1512
import { CSVData } from '@/components/bias-detection-interfaces/csv-data';
1613
import { useTranslation } from 'react-i18next';
1714
import LanguageSwitcher from '@/components/ui/languageSwitcher';
18-
import {
19-
DropdownMenu,
20-
DropdownMenuContent,
21-
DropdownMenuItem,
22-
DropdownMenuTrigger,
23-
} from '@/components/ui/dropdown-menu';
2415
import { LoadingState } from '@/components/LoadingState';
16+
import { ExportButton } from '@/components/bias-detection/export-button';
2517

2618
const PAGE_STYLE = `
2719
@page {
@@ -166,47 +158,12 @@ export default function BiasDetection() {
166158
>
167159
{initialised && data.data.length > 0 && result.length > 0 && (
168160
<div className="ml-auto flex flex-row gap-2 hideonprint">
169-
<DropdownMenu>
170-
<DropdownMenuTrigger asChild>
171-
<Button
172-
variant="outline"
173-
size="sm"
174-
className="p-4 text-sm"
175-
>
176-
{t('downloadButton')}
177-
<ChevronDown className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180" />
178-
</Button>
179-
</DropdownMenuTrigger>
180-
<DropdownMenuContent align="end">
181-
<DropdownMenuItem
182-
onClick={() => reactToPrintFn()}
183-
>
184-
<Share className="size-3.5 mr-2" />
185-
{t('biasSettings.exportToPDF')}
186-
</DropdownMenuItem>
187-
{clusterInfo && (
188-
<DropdownMenuItem
189-
onClick={() => {
190-
downloadFile(
191-
JSON.stringify(
192-
{
193-
fileName: data.fileName,
194-
...clusterInfo,
195-
},
196-
null,
197-
2
198-
),
199-
`${data.fileName.replace('.csv', '') || 'cluster-info'}-${clusterInfo.date.toISOString()}.json`,
200-
'application/json'
201-
);
202-
}}
203-
>
204-
<Share className="size-3.5 mr-2" />
205-
{t('biasSettings.exportToJSON')}
206-
</DropdownMenuItem>
207-
)}
208-
</DropdownMenuContent>
209-
</DropdownMenu>
161+
<ExportButton
162+
buttonAlign={'right'}
163+
clusterInfo={clusterInfo}
164+
reactToPrintFn={reactToPrintFn}
165+
data={data}
166+
/>
210167
</div>
211168
)}
212169

@@ -228,6 +185,17 @@ export default function BiasDetection() {
228185
<div className="flex-1" />
229186
</>
230187
)}
188+
189+
{initialised && data.data.length > 0 && result.length > 0 && (
190+
<div className="flex flex-row gap-2 hideonprint">
191+
<ExportButton
192+
buttonAlign={'center'}
193+
clusterInfo={clusterInfo}
194+
reactToPrintFn={reactToPrintFn}
195+
data={data}
196+
/>
197+
</div>
198+
)}
231199
</div>
232200
</main>
233201
);

0 commit comments

Comments
 (0)