Skip to content

Commit 8ce3163

Browse files
authored
🐛 Add taskgroup when uploading binary (#1280)
- 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]>
1 parent 435b73a commit 8ce3163

File tree

6 files changed

+111
-68
lines changed

6 files changed

+111
-68
lines changed

client/src/app/pages/applications/analysis-wizard/analysis-wizard.tsx

+13-32
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { useTranslation } from "react-i18next";
1010

1111
import {
1212
Application,
13-
IReadFile,
1413
TaskData,
1514
Taskgroup,
1615
TaskgroupTask,
@@ -36,9 +35,8 @@ import {
3635
} from "./schema";
3736
import { useAsyncYupValidation } from "@app/hooks/useAsyncYupValidation";
3837
import { CustomRules } from "./custom-rules";
39-
import { useSetting } from "@app/queries/settings";
40-
import defaultSources from "./sources";
4138
import { useFetchIdentities } from "@app/queries/identities";
39+
import { TaskGroupProvider, useTaskGroup } from "./components/TaskGroupContext";
4240

4341
interface IAnalysisWizard {
4442
applications: Application[];
@@ -67,7 +65,7 @@ const defaultTaskData: TaskData = {
6765
},
6866
};
6967

70-
const defaultTaskgroup: Taskgroup = {
68+
export const defaultTaskgroup: Taskgroup = {
7169
name: `taskgroup.analyzer`,
7270
addon: "analyzer",
7371
data: {
@@ -96,18 +94,16 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
9694

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

99-
const [currentTaskgroup, setCurrentTaskgroup] =
100-
React.useState<Taskgroup | null>();
97+
const { taskGroup, updateTaskGroup } = useTaskGroup();
10198

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

105102
const onCreateTaskgroupSuccess = (data: Taskgroup) => {
106-
setCurrentTaskgroup(data);
103+
updateTaskGroup(data);
107104
};
108105

109106
const onCreateTaskgroupError = (error: Error | unknown) => {
110-
console.log("Taskgroup creation failed: ", error);
111107
pushNotification({
112108
title: "Taskgroup creation failed",
113109
variant: "danger",
@@ -139,11 +135,10 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
139135
);
140136

141137
const onDeleteTaskgroupSuccess = () => {
142-
setCurrentTaskgroup(null);
138+
updateTaskGroup(null);
143139
};
144140

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

284279
const handleCancel = () => {
285-
if (currentTaskgroup && currentTaskgroup.id) {
286-
deleteTaskgroup(currentTaskgroup.id);
280+
if (taskGroup && taskGroup.id) {
281+
deleteTaskgroup(taskGroup.id);
287282
}
288-
setCurrentTaskgroup(null);
283+
updateTaskGroup(null);
289284
reset();
290285
onClose();
291286
};
292287

293288
const onSubmit = (fieldValues: AnalysisWizardFormValues) => {
294-
if (currentTaskgroup) {
295-
const taskgroup = setupTaskgroup(currentTaskgroup, fieldValues);
289+
if (taskGroup) {
290+
const taskgroup = setupTaskgroup(taskGroup, fieldValues);
296291
submitTaskgroup(taskgroup);
297292
}
298-
setCurrentTaskgroup(null);
293+
updateTaskGroup(null);
299294
reset();
300295
onClose();
301296
};
@@ -306,7 +301,7 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
306301
) => {
307302
if (id && stepIdReached < (id as number)) setStepIdReached(id as number);
308303
if (id === StepId.SetTargets) {
309-
if (!currentTaskgroup) {
304+
if (!taskGroup) {
310305
createTaskgroup(defaultTaskgroup);
311306
}
312307
}
@@ -335,11 +330,6 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
335330
component: (
336331
<SetMode
337332
isSingleApp={applications.length === 1 ? true : false}
338-
taskgroupID={
339-
currentTaskgroup && currentTaskgroup?.id
340-
? currentTaskgroup.id
341-
: null
342-
}
343333
isModeValid={isModeValid}
344334
/>
345335
),
@@ -365,15 +355,7 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
365355
{
366356
id: StepId.CustomRules,
367357
name: t("wizard.terms.customRules"),
368-
component: (
369-
<CustomRules
370-
taskgroupID={
371-
currentTaskgroup && currentTaskgroup?.id
372-
? currentTaskgroup.id
373-
: null
374-
}
375-
/>
376-
),
358+
component: <CustomRules />,
377359
...getStepNavProps(StepId.CustomRules),
378360
},
379361
{
@@ -392,7 +374,6 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
392374
...getStepNavProps(StepId.Review),
393375
},
394376
];
395-
396377
return (
397378
<>
398379
{isOpen && (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Taskgroup } from "@app/api/models";
2+
import React, { createContext, useContext, useState } from "react";
3+
4+
interface TaskGroupContext {
5+
updateTaskGroup: (taskGroup: Taskgroup | null) => void;
6+
taskGroup: Taskgroup | null;
7+
}
8+
9+
const TaskGroupContext = createContext<TaskGroupContext>({
10+
updateTaskGroup: () => {},
11+
taskGroup: null,
12+
});
13+
14+
export const useTaskGroup = () => useContext(TaskGroupContext);
15+
16+
interface TaskGroupProvider {
17+
children: React.ReactNode;
18+
}
19+
20+
export const TaskGroupProvider: React.FunctionComponent<TaskGroupProvider> = ({
21+
children,
22+
}) => {
23+
const [taskGroup, setTaskGroup] = useState<Taskgroup | null>(null);
24+
25+
const updateTaskGroup = (newTaskGroup: Taskgroup | null) => {
26+
setTaskGroup(newTaskGroup);
27+
};
28+
29+
return (
30+
<TaskGroupContext.Provider value={{ taskGroup, updateTaskGroup }}>
31+
{children}
32+
</TaskGroupContext.Provider>
33+
);
34+
};

client/src/app/pages/applications/analysis-wizard/components/upload-binary.tsx

+47-15
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
1010
import { useFormContext } from "react-hook-form";
1111

1212
import {
13+
useCreateTaskgroupMutation,
1314
useRemoveUploadedFileMutation,
1415
useUploadFileTaskgroupMutation,
1516
} from "@app/queries/taskgroups";
@@ -19,12 +20,12 @@ import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
1920
import { uploadLimit } from "@app/Constants";
2021
import { NotificationsContext } from "@app/components/NotificationsContext";
2122
import { AnalysisWizardFormValues } from "../schema";
23+
import { useTaskGroup } from "./TaskGroupContext";
24+
import { Taskgroup } from "@app/api/models";
25+
import { defaultTaskgroup } from "../analysis-wizard";
2226

23-
interface IUploadBinary {
24-
taskgroupID: number;
25-
}
26-
27-
export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
27+
export const UploadBinary: React.FC = () => {
28+
const { taskGroup, updateTaskGroup } = useTaskGroup();
2829
const { setValue, watch } = useFormContext<AnalysisWizardFormValues>();
2930
const artifact = watch("artifact");
3031

@@ -90,6 +91,22 @@ export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
9091
completedRemove,
9192
failedRemove
9293
);
94+
const onCreateTaskgroupSuccess = (data: Taskgroup) => {
95+
updateTaskGroup(data);
96+
};
97+
98+
const onCreateTaskgroupError = (error: Error | unknown) => {
99+
console.log("Taskgroup creation failed: ", error);
100+
pushNotification({
101+
title: "Taskgroup creation failed",
102+
variant: "danger",
103+
});
104+
};
105+
106+
const { mutateAsync: createTaskgroup } = useCreateTaskgroupMutation(
107+
onCreateTaskgroupSuccess,
108+
onCreateTaskgroupError
109+
);
93110

94111
const handleFileDrop = (_: DropEvent, droppedFiles: File[]) => {
95112
if (droppedFiles[0]) {
@@ -98,12 +115,26 @@ export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
98115
setFileUploadStatus(undefined);
99116
const form = new FormData();
100117
form.append("file", droppedFiles[0]);
101-
uploadFile({
102-
id: taskgroupID,
103-
path: `binary/${droppedFiles[0].name}`,
104-
formData: form,
105-
file: droppedFiles[0],
106-
});
118+
if (!taskGroup) {
119+
createTaskgroup(defaultTaskgroup).then((data) => {
120+
updateTaskGroup(data);
121+
data.id &&
122+
uploadFile({
123+
id: data?.id,
124+
path: `binary/${droppedFiles[0].name}`,
125+
formData: form,
126+
file: droppedFiles[0],
127+
});
128+
});
129+
} else {
130+
taskGroup.id &&
131+
uploadFile({
132+
id: taskGroup?.id,
133+
path: `binary/${droppedFiles[0].name}`,
134+
formData: form,
135+
file: droppedFiles[0],
136+
});
137+
}
107138
setValue("artifact", droppedFiles[0]);
108139
}
109140
};
@@ -175,10 +206,11 @@ export const UploadBinary: React.FC<IUploadBinary> = ({ taskgroupID }) => {
175206
key={artifact.name}
176207
customFileHandler={handleFile}
177208
onClearClick={() => {
178-
removeFile({
179-
id: taskgroupID,
180-
path: `binary/${artifact}`,
181-
});
209+
taskGroup?.id &&
210+
removeFile({
211+
id: taskGroup?.id,
212+
path: `binary/${artifact}`,
213+
});
182214
setValue("artifact", null);
183215
}}
184216
progressAriaLabel={"text"}

client/src/app/pages/applications/analysis-wizard/custom-rules.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ import { OptionWithValue, SimpleSelect } from "@app/components/SimpleSelect";
5454
import { toOptionLike } from "@app/utils/model-utils";
5555
import { useFetchIdentities } from "@app/queries/identities";
5656
import useRuleFiles from "@app/hooks/useRuleFiles";
57-
interface CustomRulesProps {
58-
taskgroupID: number | null;
59-
}
60-
export const CustomRules: React.FC<CustomRulesProps> = (props) => {
57+
import { useTaskGroup } from "./components/TaskGroupContext";
58+
59+
export const CustomRules: React.FC = () => {
6160
const { t } = useTranslation();
61+
const { taskGroup, updateTaskGroup } = useTaskGroup();
6262

6363
const { watch, setValue, control, getValues } =
6464
useFormContext<AnalysisWizardFormValues>();
@@ -92,7 +92,7 @@ export const CustomRules: React.FC<CustomRulesProps> = (props) => {
9292
successfullyReadFileCount,
9393
handleFile,
9494
removeFiles,
95-
} = useRuleFiles(props?.taskgroupID, values.customRulesFiles);
95+
} = useRuleFiles(taskGroup?.id, values.customRulesFiles);
9696

9797
const repositoryTypeOptions: OptionWithValue<string>[] = [
9898
{

client/src/app/pages/applications/analysis-wizard/set-mode.tsx

+2-9
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,10 @@ import { HookFormPFGroupController } from "@app/components/HookFormPFFields";
1111

1212
interface ISetMode {
1313
isSingleApp: boolean;
14-
taskgroupID: number | null;
1514
isModeValid: boolean;
1615
}
1716

18-
export const SetMode: React.FC<ISetMode> = ({
19-
isSingleApp,
20-
taskgroupID,
21-
isModeValid,
22-
}) => {
17+
export const SetMode: React.FC<ISetMode> = ({ isSingleApp, isModeValid }) => {
2318
const { t } = useTranslation();
2419

2520
const { watch, control, setValue } =
@@ -89,9 +84,7 @@ export const SetMode: React.FC<ISetMode> = ({
8984
<p>{t("wizard.label.notAllAnalyzableDetails")}</p>
9085
</Alert>
9186
)}
92-
{mode === "binary-upload" && taskgroupID && (
93-
<UploadBinary taskgroupID={taskgroupID} />
94-
)}
87+
{mode === "binary-upload" && <UploadBinary />}
9588
</Form>
9689
);
9790
};

client/src/app/pages/applications/applications-table-analyze/applications-table-analyze.tsx

+10-7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import { AppTableWithControls } from "@app/components/AppTableWithControls";
7070
import { ToolbarBulkSelector } from "@app/components/ToolbarBulkSelector";
7171
import { KebabDropdown } from "@app/components/KebabDropdown";
7272
import { NoDataEmptyState } from "@app/components/NoDataEmptyState";
73+
import { TaskGroupProvider } from "../analysis-wizard/components/TaskGroupContext";
7374

7475
const ENTITY_FIELD = "entity";
7576

@@ -611,13 +612,15 @@ export const ApplicationsTableAnalyze: React.FC = () => {
611612
onClose={() => setSaveApplicationsModalState(null)}
612613
/>
613614
</Modal>{" "}
614-
<AnalysisWizard
615-
applications={selectedRows}
616-
isOpen={isAnalyzeModalOpen}
617-
onClose={() => {
618-
setAnalyzeModalOpen(false);
619-
}}
620-
/>
615+
<TaskGroupProvider>
616+
<AnalysisWizard
617+
applications={selectedRows}
618+
isOpen={isAnalyzeModalOpen}
619+
onClose={() => {
620+
setAnalyzeModalOpen(false);
621+
}}
622+
/>
623+
</TaskGroupProvider>
621624
<Modal
622625
isOpen={isApplicationImportModalOpen}
623626
variant="medium"

0 commit comments

Comments
 (0)