Skip to content

Commit

Permalink
✨ Add cancel option for multiple analyses (#2099)
Browse files Browse the repository at this point in the history
Added support for cancelling multiple analyses simultaneously.
Integrated functionality into the actions menu for bulk applications.
Resolves: https://issues.redhat.com/browse/MTA-3639

---------

Signed-off-by: MiriSafra <[email protected]>
Signed-off-by: shevijacobson <[email protected]>
Co-authored-by: shevijacobson <[email protected]>
  • Loading branch information
MiriSafra and Shevijacobson authored Nov 4, 2024
1 parent 0cfe60b commit 2bc6eb1
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 5 deletions.
6 changes: 6 additions & 0 deletions client/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"accept": "Accept",
"back": "Back",
"cancel": "Cancel",
"cancelTasks": "Cancel tasks",
"checkDocumentation": "Check documentation",
"clearAllFilters": "Clear all filters",
"clearRepositoryNotSupported": "This action is disabled when RWX volumes are not available",
Expand Down Expand Up @@ -107,7 +108,9 @@
"dialog": {
"message": {
"applicationsBulkDelete": "The selected application(s) will be deleted.",
"TasksBulkCancel": "The selected task(s) will be canceled.",
"delete": "This action cannot be undone.",
"cancel": "This action cannot be undone.",
"discardAssessment": "The assessment(s) for <1>{{applicationName}}</1> will be discarded. Do you wish to continue?",
"discardReview": "The review for <1>{{applicationName}}</1> will be discarded. Do you wish to continue?",
"leavePage": "Are you sure you want to leave this page? Be sure to save your changes, or they will be lost.",
Expand All @@ -124,7 +127,9 @@
"copyApplicationAssessmentAndReviewFrom": "Copy {{what}} assessment and review",
"copyApplicationAssessmentFrom": "Copy {{what}} assessment",
"delete": "Delete {{what}}?",
"cancel": "Cancel {{what}}?",
"deleteWithName": "Delete {{what}} \"{{name}}\"?",
"cancelWithName": "Cancel {{what}} \"{{name}}\"?",
"discard": "Discard {{what}}?",
"download": "Download {{what}}",
"edit": "Edit {{what}}",
Expand Down Expand Up @@ -481,6 +486,7 @@
"tagCategoryDeleted": "Tag category deleted",
"tagCategories": "Tag categories",
"tasks": "Tasks",
"task": "Task",
"teamMember": "team member",
"terminated": "Terminated",
"ticket": "Ticket",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ export const ApplicationsTable: React.FC = () => {

const history = useHistory();
const token = keycloak.tokenParsed;

// ----- State for the modals
const [saveApplicationModalState, setSaveApplicationModalState] = useState<
"create" | DecoratedApplication | null
Expand Down Expand Up @@ -156,7 +155,9 @@ export const ApplicationsTable: React.FC = () => {
const [applicationsToDelete, setApplicationsToDelete] = useState<
DecoratedApplication[]
>([]);

const [tasksToCancel, setTasksToCancel] = useState<DecoratedApplication[]>(
[]
);
const [assessmentToDiscard, setAssessmentToDiscard] =
useState<DecoratedApplication | null>(null);

Expand Down Expand Up @@ -214,7 +215,7 @@ export const ApplicationsTable: React.FC = () => {

const isTaskCancellable = (application: DecoratedApplication) => {
const task = application.tasks.currentAnalyzer;
return !TaskStates.Terminal.includes(task?.state ?? "");
return !!task && !TaskStates.Terminal.includes(task?.state ?? "");
};

// TODO: Review the refetchInterval calculation for the application list
Expand Down Expand Up @@ -272,7 +273,6 @@ export const ApplicationsTable: React.FC = () => {
});
}
);

const discardReview = async (application: DecoratedApplication) => {
if (application.review) {
deleteReview({
Expand All @@ -297,7 +297,6 @@ export const ApplicationsTable: React.FC = () => {
});
}
);

const discardAssessment = async (application: DecoratedApplication) => {
if (application.assessments) {
application.assessments.forEach((assessment) => {
Expand Down Expand Up @@ -575,6 +574,23 @@ export const ApplicationsTable: React.FC = () => {
>
{t("actions.delete")}
</DropdownItem>,
...(tasksReadAccess && tasksWriteAccess
? [
<DropdownItem
key="applications-bulk-cancel"
isDisabled={
!selectedRows.some((application: DecoratedApplication) =>
isTaskCancellable(application)
)
}
onClick={() => {
handleCancelBulkAnalysis();
}}
>
{t("actions.cancelAnalysis")}
</DropdownItem>,
]
: []),
...(credentialsReadAccess
? [
<DropdownItem
Expand Down Expand Up @@ -638,6 +654,12 @@ export const ApplicationsTable: React.FC = () => {
})
);
};
const handleCancelBulkAnalysis = () => {
const runningTasksToCancel = selectedRows.filter((application) =>
isTaskCancellable(application)
);
setTasksToCancel(runningTasksToCancel);
};

const assessSelectedApp = async (application: DecoratedApplication) => {
setApplicationToAssess(application);
Expand Down Expand Up @@ -1149,6 +1171,37 @@ export const ApplicationsTable: React.FC = () => {
if (ids) bulkDeleteApplication({ ids: ids });
}}
/>
<ConfirmDialog
title={t(
tasksToCancel.length > 1
? "dialog.title.cancel"
: "dialog.title.cancelWithName",
{
what:
tasksToCancel.length > 1
? t("terms.tasks").toLowerCase()
: t("terms.task").toLowerCase(),
name: tasksToCancel.length === 1 && tasksToCancel[0].name,
}
)}
titleIconVariant={"warning"}
isOpen={tasksToCancel.length > 0}
message={`${
tasksToCancel.length > 1 ? t("dialog.message.TasksBulkCancel") : ""
} ${t("dialog.message.cancel")}`}
aria-label="Tasks bulk cancel"
confirmBtnVariant={ButtonVariant.danger}
confirmBtnLabel={t("actions.cancelTasks")}
cancelBtnLabel={t("actions.cancel")}
onCancel={() => setTasksToCancel([])}
onClose={() => setTasksToCancel([])}
onConfirm={() => {
tasksToCancel.forEach((application) => {
cancelAnalysis(application);
});
setTasksToCancel([]);
}}
/>
<ConfirmDialog
title={t("dialog.title.discard", {
what: t("terms.assessment").toLowerCase(),
Expand Down

0 comments on commit 2bc6eb1

Please sign in to comment.