Skip to content

Commit

Permalink
🐛 Add taskgroup when uploading binary (#1280)
Browse files Browse the repository at this point in the history
- Improve handling of taskgroup state by using contextAPI
- Async create the taskgroup before uploading the custom binary in the
single app use case. This is currently broken because we require a task
group to exist before navigating to the upload file screen. This
regression was caused by the move away from useEffect here
#1267
Resolves https://issues.redhat.com/browse/MTA-1175

Signed-off-by: ibolton336 <[email protected]>
  • Loading branch information
ibolton336 authored Aug 17, 2023
1 parent 435b73a commit 8ce3163
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useTranslation } from "react-i18next";

import {
Application,
IReadFile,
TaskData,
Taskgroup,
TaskgroupTask,
Expand All @@ -36,9 +35,8 @@ import {
} from "./schema";
import { useAsyncYupValidation } from "@app/hooks/useAsyncYupValidation";
import { CustomRules } from "./custom-rules";
import { useSetting } from "@app/queries/settings";
import defaultSources from "./sources";
import { useFetchIdentities } from "@app/queries/identities";
import { TaskGroupProvider, useTaskGroup } from "./components/TaskGroupContext";

interface IAnalysisWizard {
applications: Application[];
Expand Down Expand Up @@ -67,7 +65,7 @@ const defaultTaskData: TaskData = {
},
};

const defaultTaskgroup: Taskgroup = {
export const defaultTaskgroup: Taskgroup = {
name: `taskgroup.analyzer`,
addon: "analyzer",
data: {
Expand Down Expand Up @@ -96,18 +94,16 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({

const { pushNotification } = React.useContext(NotificationsContext);

const [currentTaskgroup, setCurrentTaskgroup] =
React.useState<Taskgroup | null>();
const { taskGroup, updateTaskGroup } = useTaskGroup();

const [stepIdReached, setStepIdReached] = React.useState(1);
const isMutating = useIsMutating();

const onCreateTaskgroupSuccess = (data: Taskgroup) => {
setCurrentTaskgroup(data);
updateTaskGroup(data);
};

const onCreateTaskgroupError = (error: Error | unknown) => {
console.log("Taskgroup creation failed: ", error);
pushNotification({
title: "Taskgroup creation failed",
variant: "danger",
Expand Down Expand Up @@ -139,11 +135,10 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
);

const onDeleteTaskgroupSuccess = () => {
setCurrentTaskgroup(null);
updateTaskGroup(null);
};

const onDeleteTaskgroupError = (error: Error | unknown) => {
console.log("Taskgroup: delete failed: ", error);
pushNotification({
title: "Taskgroup: delete failed",
variant: "danger",
Expand Down Expand Up @@ -282,20 +277,20 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
const isModeValid = applications.every((app) => isModeSupported(app, mode));

const handleCancel = () => {
if (currentTaskgroup && currentTaskgroup.id) {
deleteTaskgroup(currentTaskgroup.id);
if (taskGroup && taskGroup.id) {
deleteTaskgroup(taskGroup.id);
}
setCurrentTaskgroup(null);
updateTaskGroup(null);
reset();
onClose();
};

const onSubmit = (fieldValues: AnalysisWizardFormValues) => {
if (currentTaskgroup) {
const taskgroup = setupTaskgroup(currentTaskgroup, fieldValues);
if (taskGroup) {
const taskgroup = setupTaskgroup(taskGroup, fieldValues);
submitTaskgroup(taskgroup);
}
setCurrentTaskgroup(null);
updateTaskGroup(null);
reset();
onClose();
};
Expand All @@ -306,7 +301,7 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
) => {
if (id && stepIdReached < (id as number)) setStepIdReached(id as number);
if (id === StepId.SetTargets) {
if (!currentTaskgroup) {
if (!taskGroup) {
createTaskgroup(defaultTaskgroup);
}
}
Expand Down Expand Up @@ -335,11 +330,6 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
component: (
<SetMode
isSingleApp={applications.length === 1 ? true : false}
taskgroupID={
currentTaskgroup && currentTaskgroup?.id
? currentTaskgroup.id
: null
}
isModeValid={isModeValid}
/>
),
Expand All @@ -365,15 +355,7 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
{
id: StepId.CustomRules,
name: t("wizard.terms.customRules"),
component: (
<CustomRules
taskgroupID={
currentTaskgroup && currentTaskgroup?.id
? currentTaskgroup.id
: null
}
/>
),
component: <CustomRules />,
...getStepNavProps(StepId.CustomRules),
},
{
Expand All @@ -392,7 +374,6 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
...getStepNavProps(StepId.Review),
},
];

return (
<>
{isOpen && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Taskgroup } from "@app/api/models";
import React, { createContext, useContext, useState } from "react";

interface TaskGroupContext {
updateTaskGroup: (taskGroup: Taskgroup | null) => void;
taskGroup: Taskgroup | null;
}

const TaskGroupContext = createContext<TaskGroupContext>({
updateTaskGroup: () => {},
taskGroup: null,
});

export const useTaskGroup = () => useContext(TaskGroupContext);

interface TaskGroupProvider {
children: React.ReactNode;
}

export const TaskGroupProvider: React.FunctionComponent<TaskGroupProvider> = ({
children,
}) => {
const [taskGroup, setTaskGroup] = useState<Taskgroup | null>(null);

const updateTaskGroup = (newTaskGroup: Taskgroup | null) => {
setTaskGroup(newTaskGroup);
};

return (
<TaskGroupContext.Provider value={{ taskGroup, updateTaskGroup }}>
{children}
</TaskGroupContext.Provider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
import { useFormContext } from "react-hook-form";

import {
useCreateTaskgroupMutation,
useRemoveUploadedFileMutation,
useUploadFileTaskgroupMutation,
} from "@app/queries/taskgroups";
Expand All @@ -19,12 +20,12 @@ import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { uploadLimit } from "@app/Constants";
import { NotificationsContext } from "@app/components/NotificationsContext";
import { AnalysisWizardFormValues } from "../schema";
import { useTaskGroup } from "./TaskGroupContext";
import { Taskgroup } from "@app/api/models";
import { defaultTaskgroup } from "../analysis-wizard";

interface IUploadBinary {
taskgroupID: number;
}

export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
export const UploadBinary: React.FC = () => {
const { taskGroup, updateTaskGroup } = useTaskGroup();
const { setValue, watch } = useFormContext<AnalysisWizardFormValues>();
const artifact = watch("artifact");

Expand Down Expand Up @@ -90,6 +91,22 @@ export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
completedRemove,
failedRemove
);
const onCreateTaskgroupSuccess = (data: Taskgroup) => {
updateTaskGroup(data);
};

const onCreateTaskgroupError = (error: Error | unknown) => {
console.log("Taskgroup creation failed: ", error);
pushNotification({
title: "Taskgroup creation failed",
variant: "danger",
});
};

const { mutateAsync: createTaskgroup } = useCreateTaskgroupMutation(
onCreateTaskgroupSuccess,
onCreateTaskgroupError
);

const handleFileDrop = (_: DropEvent, droppedFiles: File[]) => {
if (droppedFiles[0]) {
Expand All @@ -98,12 +115,26 @@ export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
setFileUploadStatus(undefined);
const form = new FormData();
form.append("file", droppedFiles[0]);
uploadFile({
id: taskgroupID,
path: `binary/${droppedFiles[0].name}`,
formData: form,
file: droppedFiles[0],
});
if (!taskGroup) {
createTaskgroup(defaultTaskgroup).then((data) => {
updateTaskGroup(data);
data.id &&
uploadFile({
id: data?.id,
path: `binary/${droppedFiles[0].name}`,
formData: form,
file: droppedFiles[0],
});
});
} else {
taskGroup.id &&
uploadFile({
id: taskGroup?.id,
path: `binary/${droppedFiles[0].name}`,
formData: form,
file: droppedFiles[0],
});
}
setValue("artifact", droppedFiles[0]);
}
};
Expand Down Expand Up @@ -175,10 +206,11 @@ export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
key={artifact.name}
customFileHandler={handleFile}
onClearClick={() => {
removeFile({
id: taskgroupID,
path: `binary/${artifact}`,
});
taskGroup?.id &&
removeFile({
id: taskGroup?.id,
path: `binary/${artifact}`,
});
setValue("artifact", null);
}}
progressAriaLabel={"text"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ import { OptionWithValue, SimpleSelect } from "@app/components/SimpleSelect";
import { toOptionLike } from "@app/utils/model-utils";
import { useFetchIdentities } from "@app/queries/identities";
import useRuleFiles from "@app/hooks/useRuleFiles";
interface CustomRulesProps {
taskgroupID: number | null;
}
export const CustomRules: React.FC<CustomRulesProps> = (props) => {
import { useTaskGroup } from "./components/TaskGroupContext";

export const CustomRules: React.FC = () => {
const { t } = useTranslation();
const { taskGroup, updateTaskGroup } = useTaskGroup();

const { watch, setValue, control, getValues } =
useFormContext<AnalysisWizardFormValues>();
Expand Down Expand Up @@ -92,7 +92,7 @@ export const CustomRules: React.FC<CustomRulesProps> = (props) => {
successfullyReadFileCount,
handleFile,
removeFiles,
} = useRuleFiles(props?.taskgroupID, values.customRulesFiles);
} = useRuleFiles(taskGroup?.id, values.customRulesFiles);

const repositoryTypeOptions: OptionWithValue<string>[] = [
{
Expand Down
11 changes: 2 additions & 9 deletions client/src/app/pages/applications/analysis-wizard/set-mode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,10 @@ import { HookFormPFGroupController } from "@app/components/HookFormPFFields";

interface ISetMode {
isSingleApp: boolean;
taskgroupID: number | null;
isModeValid: boolean;
}

export const SetMode: React.FC<ISetMode> = ({
isSingleApp,
taskgroupID,
isModeValid,
}) => {
export const SetMode: React.FC<ISetMode> = ({ isSingleApp, isModeValid }) => {
const { t } = useTranslation();

const { watch, control, setValue } =
Expand Down Expand Up @@ -89,9 +84,7 @@ export const SetMode: React.FC<ISetMode> = ({
<p>{t("wizard.label.notAllAnalyzableDetails")}</p>
</Alert>
)}
{mode === "binary-upload" && taskgroupID && (
<UploadBinary taskgroupID={taskgroupID} />
)}
{mode === "binary-upload" && <UploadBinary />}
</Form>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import { AppTableWithControls } from "@app/components/AppTableWithControls";
import { ToolbarBulkSelector } from "@app/components/ToolbarBulkSelector";
import { KebabDropdown } from "@app/components/KebabDropdown";
import { NoDataEmptyState } from "@app/components/NoDataEmptyState";
import { TaskGroupProvider } from "../analysis-wizard/components/TaskGroupContext";

const ENTITY_FIELD = "entity";

Expand Down Expand Up @@ -611,13 +612,15 @@ export const ApplicationsTableAnalyze: React.FC = () => {
onClose={() => setSaveApplicationsModalState(null)}
/>
</Modal>{" "}
<AnalysisWizard
applications={selectedRows}
isOpen={isAnalyzeModalOpen}
onClose={() => {
setAnalyzeModalOpen(false);
}}
/>
<TaskGroupProvider>
<AnalysisWizard
applications={selectedRows}
isOpen={isAnalyzeModalOpen}
onClose={() => {
setAnalyzeModalOpen(false);
}}
/>
</TaskGroupProvider>
<Modal
isOpen={isApplicationImportModalOpen}
variant="medium"
Expand Down

0 comments on commit 8ce3163

Please sign in to comment.