diff --git a/frontend/src/components/jobs/result/JobOverview.jsx b/frontend/src/components/jobs/result/JobOverview.jsx index 477d57f4b9..6d7d9f0837 100644 --- a/frontend/src/components/jobs/result/JobOverview.jsx +++ b/frontend/src/components/jobs/result/JobOverview.jsx @@ -15,7 +15,7 @@ import { Spinner, } from "reactstrap"; -import { GoBackButton, Loader } from "@certego/certego-ui"; +import { Loader } from "@certego/certego-ui"; import { JSONTree } from "react-json-tree"; import { useNavigate, useLocation } from "react-router-dom"; @@ -288,15 +288,17 @@ export function JobOverview({ render={() => ( {/* bar with job id and utilities buttons */} - + -

Job #{job.id}

- +
diff --git a/frontend/src/components/jobs/result/bar/JobActionBar.jsx b/frontend/src/components/jobs/result/bar/JobActionBar.jsx index a192b2720c..663492fe3e 100644 --- a/frontend/src/components/jobs/result/bar/JobActionBar.jsx +++ b/frontend/src/components/jobs/result/bar/JobActionBar.jsx @@ -4,12 +4,7 @@ import { Button } from "reactstrap"; import { useNavigate } from "react-router-dom"; import { FaFileDownload } from "react-icons/fa"; -import { - ContentSection, - SocialShareBtn, - IconButton, - addToast, -} from "@certego/certego-ui"; +import { ContentSection, IconButton, addToast } from "@certego/certego-ui"; import { SaveAsPlaybookButton } from "./SaveAsPlaybooksForm"; @@ -17,7 +12,12 @@ import { downloadJobSample, deleteJob } from "../jobApi"; import { createJob } from "../../../scan/scanApi"; import { ScanModesNumeric } from "../../../../constants/advancedSettingsConst"; import { JobResultSections } from "../../../../constants/miscConst"; -import { DeleteIcon, CommentIcon, retryJobIcon } from "../utils/icons"; +import { + DeleteIcon, + CommentIcon, + retryJobIcon, + downloadReportIcon, +} from "../utils/icons"; export function JobActionsBar({ job }) { // routers @@ -31,24 +31,26 @@ export function JobActionsBar({ job }) { setTimeout(() => navigate(-1), 250); }; - const onDownloadSampleBtnClick = async () => { - const blob = await downloadJobSample(job.id); - if (!blob) return; + const fileDownload = (blob, filename) => { // create URL blob and a hidden tag to serve file for download const fileLink = document.createElement("a"); fileLink.href = window.URL.createObjectURL(blob); fileLink.rel = "noopener,noreferrer"; - if (job?.file_name) { - // it forces the name of the downloaded file - fileLink.download = `${job.file_name}`; - } + fileLink.download = `${filename}`; // triggers the click event fileLink.click(); }; - const shareText = `Checkout this job (#${job.id}, ${ - job.is_sample ? job.file_name : job.observable_name - }) on IntelOwl`; + const onDownloadSampleBtnClick = async () => { + const blob = await downloadJobSample(job.id); + if (!blob) return; + let filename = "file"; + if (job?.file_name) { + // it forces the name of the downloaded file + filename = `${job.file_name}`; + } + fileDownload(blob, filename); + }; const handleRetry = async () => { if (job.is_sample) { @@ -80,6 +82,14 @@ export function JobActionsBar({ job }) { } }; + const onDownloadReport = () => { + if (job) { + const blob = new Blob([JSON.stringify(job)], { type: "text/json" }); + if (!blob) return; + fileDownload(blob, `job#${job.id}_report.json`); + } + }; + const commentIcon = () => ; return ( @@ -110,29 +120,32 @@ export function JobActionsBar({ job }) { Icon={retryJobIcon} onClick={handleRetry} color="light" - size="xs" + size="sm" title="Force run the same analysis" titlePlacement="top" className="me-2" /> - {job?.is_sample && ( )} - ); diff --git a/frontend/src/components/jobs/result/bar/SaveAsPlaybooksForm.jsx b/frontend/src/components/jobs/result/bar/SaveAsPlaybooksForm.jsx index 5eed821650..8ddecb8d1f 100644 --- a/frontend/src/components/jobs/result/bar/SaveAsPlaybooksForm.jsx +++ b/frontend/src/components/jobs/result/bar/SaveAsPlaybooksForm.jsx @@ -140,7 +140,6 @@ export function SaveAsPlaybookButton({ job }) { return ( ); } + +export function downloadReportIcon() { + return ( + + + Report + + ); +} diff --git a/frontend/src/layouts/AppHeader.jsx b/frontend/src/layouts/AppHeader.jsx index e771fede15..8e1f0de7eb 100644 --- a/frontend/src/layouts/AppHeader.jsx +++ b/frontend/src/layouts/AppHeader.jsx @@ -12,7 +12,6 @@ import { } from "reactstrap"; import { NavLink as RRNavLink, useLocation } from "react-router-dom"; import { AiOutlineDashboard } from "react-icons/ai"; -import { SiHackaday } from "react-icons/si"; import { MdHome, MdShare } from "react-icons/md"; import { RiFileListFill, @@ -22,6 +21,7 @@ import { RiTwitterXFill, } from "react-icons/ri"; import { FaGithub, FaGoogle } from "react-icons/fa"; +import { IoSearch } from "react-icons/io5"; // lib import { NavLink, AxiosLoadingBar } from "@certego/certego-ui"; @@ -64,7 +64,7 @@ const authLinks = ( - + Scan diff --git a/frontend/tests/components/jobs/result/JobOverview.test.jsx b/frontend/tests/components/jobs/result/JobOverview.test.jsx index 5ae9eb8fcb..6979e6105d 100644 --- a/frontend/tests/components/jobs/result/JobOverview.test.jsx +++ b/frontend/tests/components/jobs/result/JobOverview.test.jsx @@ -76,8 +76,6 @@ describe("test JobOverview (job report)", () => { // utility bar const utilitiesRow = container.querySelector("#utilitiesRow"); expect(within(utilitiesRow).getByText("Job #1")).toBeInTheDocument(); - const goBackButton = within(utilitiesRow).getByRole("button", { name: "" }); - expect(goBackButton.id).toBe("gobackbutton"); expect( within(utilitiesRow).getByRole("button", { name: "Comments (1)" }), ).toBeInTheDocument(); @@ -91,7 +89,7 @@ describe("test JobOverview (job report)", () => { within(utilitiesRow).getByRole("button", { name: "Save As Playbook" }), ).toBeInTheDocument(); expect( - within(utilitiesRow).getByRole("button", { name: "Share" }), + within(utilitiesRow).getByRole("button", { name: "Report" }), ).toBeInTheDocument(); });