Path: blob/main/components/dashboard/src/insights/download/DownloadInsights.tsx
2501 views
/**1* Copyright (c) 2024 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { useCallback, useEffect, useMemo, useState } from "react";7import { AlertTriangle } from "lucide-react";8import prettyBytes from "pretty-bytes";9import { Button } from "@podkit/buttons/Button";10import { useDownloadSessionsCSV } from "./download-sessions";11import { Timestamp } from "@bufbuild/protobuf";12import saveAs from "file-saver";1314type Props = {15from: Timestamp;16to: Timestamp;17organizationId: string;18organizationName: string;19};20export const DownloadInsightsToast = ({ organizationId, from, to, organizationName }: Props) => {21const [progress, setProgress] = useState(0);2223const queryArgs = useMemo(24() => ({25organizationName,26organizationId,27from,28to,29onProgress: setProgress,30}),31[from, organizationId, organizationName, to],32);33const { data, error, isLoading, abort, remove } = useDownloadSessionsCSV(queryArgs);3435const saveFile = useCallback(() => {36if (!data || !data.blob) {37return;38}3940saveAs(data.blob, data.filename);41}, [data]);4243useEffect(() => {44return () => {45abort();46remove();47};48// eslint-disable-next-line react-hooks/exhaustive-deps49}, []);5051if (isLoading) {52return (53<div>54<span>Preparing insights export</span>55<br />56<span className="text-sm">Exporting page {progress}</span>57</div>58);59}6061if (error) {62return (63<div className="flex flex-row items-start space-x-2">64<AlertTriangle className="w-5 h-5 mt-0.5" />65<div>66<span>Error exporting your insights data:</span>67<pre className="mt-2 whitespace-normal text-sm">{error.message}</pre>68</div>69</div>70);71}7273if (!data || !data.blob || data.count === 0) {74return <span>No insights data for the selected period.</span>;75}7677const readableSize = prettyBytes(data.blob.size);78const formattedCount = Intl.NumberFormat().format(data.count);7980return (81<div className="flex flex-row items-start justify-between space-x-2">82<div>83<span>Insights export complete.</span>84<p className="text-pk-content-invert-primary/90">85{readableSize} · {formattedCount} {data.count !== 1 ? "entries" : "entry"} exported86</p>87</div>88<div>89<Button onClick={saveFile} className="text-left text-base">90Download CSV91</Button>92</div>93</div>94);95};969798