Skip to content

Commit

Permalink
🐛 FIx broken analysis report download
Browse files Browse the repository at this point in the history
Signed-off-by: ibolton336 <[email protected]>
  • Loading branch information
ibolton336 committed Sep 27, 2023
1 parent 9cf7840 commit a7cb60c
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,7 @@ export const ApplicationDetailDrawerAnalysis: React.FC<
<DownloadButton
id={application.id}
mimeType={MimeType.TAR}
>
TAR
</DownloadButton>
/>
</Tooltip>
{" | "}
<Tooltip
Expand All @@ -153,9 +151,7 @@ export const ApplicationDetailDrawerAnalysis: React.FC<
<DownloadButton
id={application.id}
mimeType={MimeType.YAML}
>
YAML
</DownloadButton>
/>
</Tooltip>
</DescriptionListDescription>
</DescriptionListGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,55 @@
import React from "react";
import { Button } from "@patternfly/react-core";
import { Alert, Button } from "@patternfly/react-core";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { saveAs } from "file-saver";

import { MimeType } from "@app/api/models";
import { useFetchStaticReport } from "@app/queries/applications";
import { NotificationsContext } from "@app/components/NotificationsContext";
import { AxiosError } from "axios";
import { getAxiosErrorMessage } from "@app/utils/utils";
import { Spinner } from "@patternfly/react-core";
import { useDownloadStaticReport } from "@app/queries/applications";

export enum MimeType {
TAR = "tar",
YAML = "yaml",
}
interface IDownloadButtonProps {
id: number;
mimeType: MimeType;
children: React.ReactNode;
}

export const DownloadButton: React.FC<IDownloadButtonProps> = ({
id,
mimeType,
children,
}) => {
const { pushNotification } = React.useContext(NotificationsContext);

const onFetchStaticReportError = (error: AxiosError) => {
pushNotification({
title: getAxiosErrorMessage(error),
variant: "danger",
});
};

const { data: report, refetch } = useFetchStaticReport(
id,
mimeType,
onFetchStaticReportError
);
const {
mutate: downloadFile,
isLoading,
isError,
} = useDownloadStaticReport();

const handleDownload = () => {
refetch().then(() => {
if (report) {
saveAs(new Blob([report]), `analysis-report-app-${id}.${mimeType}`);
}
downloadFile({
applicationId: id,
mimeType: mimeType,
});
};

return (
<Button
key={mimeType}
onClick={handleDownload}
id={`download-${mimeType}-button`}
variant="link"
className={spacing.pXs}
>
{children}
</Button>
<>
{isLoading ? (
<Spinner size="sm" />
) : isError ? (
<Alert variant="warning" isInline title={"Error downloading report"}>
<p>{"An error has occurred. Try to download again."}</p>
</Alert>
) : (
<>
<Button
onClick={handleDownload}
id={`download-${mimeType}-button`}
variant="link"
className={spacing.pXs}
>
{mimeType === MimeType.YAML ? "YAML" : "Report"}
</Button>
</>
)}
</>
);
};

Expand Down
63 changes: 49 additions & 14 deletions client/src/app/queries/applications.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
import axios, { AxiosError } from "axios";

import { MimeType } from "@app/api/models";
import {
APPLICATIONS,
createApplication,
deleteApplication,
deleteBulkApplications,
getApplicationAnalysis,
getApplicationById,
getApplications,
updateAllApplications,
updateApplication,
} from "@app/api/rest";
import { reviewsQueryKey } from "./reviews";
import { assessmentsQueryKey } from "./assessments";
import saveAs from "file-saver";

export const ApplicationDependencyQueryKey = "applicationdependencies";
export const ApplicationsQueryKey = "applications";
export const ReportQueryKey = "report";

interface DownloadOptions {
applicationId: number;
mimeType: MimeType;
}

export const useFetchApplications = () => {
const queryClient = useQueryClient();
const { isLoading, error, refetch, data } = useQuery({
Expand Down Expand Up @@ -134,15 +140,44 @@ export const useBulkDeleteApplicationMutation = (
);
};

// The report download is triggerred on demand by a refetch()
export const useFetchStaticReport = (
id: number,
type: MimeType,
onError: (err: AxiosError) => void
) =>
useQuery({
queryKey: [ReportQueryKey, id],
queryFn: () => getApplicationAnalysis(id, type),
onError: onError,
enabled: false,
});
export const downloadStaticReport = async ({
applicationId,
mimeType,
}: DownloadOptions): Promise<void> => {
const yamlAcceptHeader = "application/x-yaml";
let url = `${APPLICATIONS}/${applicationId}/analysis/report`;

Check warning on line 148 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L146-L148

Added lines #L146 - L148 were not covered by tests

switch (mimeType) {
case MimeType.YAML:
url = `${APPLICATIONS}/${applicationId}/analysis`;
break;
case MimeType.TAR:
default:
url = `${APPLICATIONS}/${applicationId}/analysis/report`;

Check warning on line 156 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L151-L156

Added lines #L151 - L156 were not covered by tests
}

try {
const response = await axios.get(url, {

Check warning on line 160 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L159-L160

Added lines #L159 - L160 were not covered by tests
responseType: "blob",
...(MimeType.YAML && {
headers: {
Accept: yamlAcceptHeader,
},
}),
});

if (response.status !== 200) {
throw new Error("Network response was not ok when downloading file.");

Check warning on line 170 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L170

Added line #L170 was not covered by tests
}

const blob = new Blob([response.data]);
saveAs(blob, `analysis-report-app-${applicationId}.${mimeType}`);

Check warning on line 174 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L173-L174

Added lines #L173 - L174 were not covered by tests
} catch (error) {
console.error("There was an error downloading the file:", error);
throw error;

Check warning on line 177 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L176-L177

Added lines #L176 - L177 were not covered by tests
}
};

export const useDownloadStaticReport = () => {
return useMutation(downloadStaticReport);

Check warning on line 182 in client/src/app/queries/applications.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/applications.ts#L182

Added line #L182 was not covered by tests
};

0 comments on commit a7cb60c

Please sign in to comment.