From 7bdf3a32e89d1b35871be0198d6b6d511a7e7679 Mon Sep 17 00:00:00 2001 From: Bruno FS Ciconelle Date: Tue, 5 Nov 2024 13:59:34 -0300 Subject: [PATCH 1/2] chore: add a utility script to make development easier npm run start:using-server will serve the development UI properly wired to a running instance of quipucords server. Default configuration points to quipucords-installer defaults, and can be customized with QUIPUCORDS_SERVER_* variables. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 359cd8c3..f1d1de17 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "build:pre": "bash ./scripts/pre.sh", "release": "changelog --link-url https://github.com/quipucords/quipucords-ui.git", "start": "export PROTOCOL=http; export HOST=127.0.0.1; export PORT=${PORT:-3000}; export MOCK_PORT=${MOCK_PORT:-3030}; run-p -l api:dev start:js start:open", + "start:using-server": "export PROTOCOL=${QUIPUCORDS_SERVER_PROTOCOL:-https}; export HOST=${QUIPUCORDS_SERVER_HOST:-127.0.0.1}; export PORT=${PORT:-3000}; export MOCK_PORT=${QUIPUCORDS_SERVER_PORT:-9443}; run-p -l start:js start:open", "start:js": "export NODE_ENV=development; weldable -l ts -x ./config/webpack.dev.js", "start:open": "xdg-open $PROTOCOL://$HOST:$PORT/ || open $PROTOCOL://$HOST:$PORT/", "start:stage": "export PROTOCOL=http; export HOST=127.0.0.1; export PORT=${PORT:-3000}; export MOCK_PORT=${MOCK_PORT:-8000}; run-p -l api:stage start:js start:open", From b7392eed4df7f2a702683dbc82058ba080315712 Mon Sep 17 00:00:00 2001 From: Bruno FS Ciconelle Date: Wed, 6 Nov 2024 13:14:08 -0300 Subject: [PATCH 2/2] feat(ActionMenu): ds-437 add download report button The button shall only be enabled when the scan is completed. --- public/locales/en.json | 2 ++ src/components/actionMenu/actionMenu.tsx | 3 ++- src/hooks/useScanApi.ts | 13 ++++++++++++- src/views/scans/viewScansList.tsx | 7 +++++++ tests/__snapshots__/code.test.ts.snap | 4 ++-- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index 506c1a81..5b8363c4 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -173,6 +173,7 @@ "label_satellite": "Satellite", "label_rhacs": "RHACS", "label_rescan": "Rescan", + "label_download": "Download", "label_scan": "Scan", "label_source": "Source", "label_source_other": "Sources", @@ -276,6 +277,7 @@ "description_scan-jobs_fetched_error": "Error displaying connection information. {{message}", "description_report_downloaded": "Report {{name}} downloaded successfully.", "description_report_downloaded_error": "Failed to download report {{name}}: {{message}}", + "description_report_downloaded_error_no_report": "The report doesn't exist.", "description_scan-report_start": "$t(toast-notifications.description_scan-report_play)", "title_add-source_hidden_error": "Error creating source {{ name }}. {{ message }}", "title_add-source_hidden_error_edit": "Error updating source {{ name }}. {{ message }}" diff --git a/src/components/actionMenu/actionMenu.tsx b/src/components/actionMenu/actionMenu.tsx index ba28f49a..448b9c96 100644 --- a/src/components/actionMenu/actionMenu.tsx +++ b/src/components/actionMenu/actionMenu.tsx @@ -11,7 +11,7 @@ import { EllipsisVIcon } from '@patternfly/react-icons'; interface ActionMenuProps { item: T; - actions: { label: string; onClick: (item: T) => void }[]; + actions: { label: string; onClick: (item: T) => void; disabled?: boolean }[]; } const ActionMenu = ({ item, actions }: ActionMenuProps) => { @@ -43,6 +43,7 @@ const ActionMenu = ({ item, actions }: ActionMenuProps) => { onClick={() => { a.onClick(item); }} + isDisabled={a.disabled} > {a.label} diff --git a/src/hooks/useScanApi.ts b/src/hooks/useScanApi.ts index 51f8aad3..90231b2b 100644 --- a/src/hooks/useScanApi.ts +++ b/src/hooks/useScanApi.ts @@ -343,8 +343,19 @@ const useDownloadReportApi = (onAddAlert: (alert: AlertProps) => void) => { [onAddAlert, t] ); + const callbackErrorNoReport = useCallback(() => { + onAddAlert({ + title: t('toast-notifications.description_report_downloaded_error_no_report'), + variant: 'danger' + }); + return; + }, [onAddAlert, t]); + const downloadReport = useCallback( - async (reportId: number) => { + async (reportId: number | undefined) => { + if (!reportId) { + return callbackErrorNoReport(); + } let response; try { response = await apiCall(reportId); diff --git a/src/views/scans/viewScansList.tsx b/src/views/scans/viewScansList.tsx index 6b9097f0..e168bbf9 100644 --- a/src/views/scans/viewScansList.tsx +++ b/src/views/scans/viewScansList.tsx @@ -250,6 +250,13 @@ const ScansListView: React.FunctionComponent = () => { setScanSelected(undefined); }); } + }, + { + label: t('table.label', { context: 'download' }), + disabled: scan.most_recent?.status === 'completed' ? false : true, + onClick: () => { + downloadReport(scan.most_recent?.report_id); + } } ]} /> diff --git a/tests/__snapshots__/code.test.ts.snap b/tests/__snapshots__/code.test.ts.snap index 6bb61431..c4a6fe43 100644 --- a/tests/__snapshots__/code.test.ts.snap +++ b/tests/__snapshots__/code.test.ts.snap @@ -22,8 +22,8 @@ exports[`General code checks should only have specific console.[warn|log|info|er "hooks/useScanApi.ts:195: console.log(missingScansMsg);", "hooks/useScanApi.ts:229: console.error(error);", "hooks/useScanApi.ts:283: console.error(error);", - "hooks/useScanApi.ts:356: console.error(error);", - "hooks/useScanApi.ts:401: console.error(error);", + "hooks/useScanApi.ts:367: console.error(error);", + "hooks/useScanApi.ts:412: console.error(error);", "hooks/useSourceApi.ts:63: console.log(missingSourcesMsg);", "hooks/useSourceApi.ts:81: console.log(missingSourcesMsg);", "hooks/useSourceApi.ts:127: console.error(error);",