From 870f5c34fd88043234413d91503c4ede89e5746b Mon Sep 17 00:00:00 2001 From: Marek Aufart Date: Tue, 30 Sep 2025 14:56:54 +0200 Subject: [PATCH 1/4] Fix multiple custom rules upload When uploading multiple custom rules in analyzer wizard, only last one was corectly processed for it s rules, updating code to make sure each uploaded file processed. Used claude code to help with this change. Signed-off-by: Marek Aufart --- .../app/components/CustomRuleFilesUpload.tsx | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/client/src/app/components/CustomRuleFilesUpload.tsx b/client/src/app/components/CustomRuleFilesUpload.tsx index 13b8ccfab..9ac2afaa2 100644 --- a/client/src/app/components/CustomRuleFilesUpload.tsx +++ b/client/src/app/components/CustomRuleFilesUpload.tsx @@ -85,6 +85,19 @@ export const CustomRuleFilesUpload: React.FC = ({ status: "starting", })); onAddRuleFiles(newRuleFiles); + }) + .then(() => { + // Trigger the upload process for each file automatically + incomingFiles.forEach((file) => { + const ruleFile = { + fileName: file.name, + fullFile: file, + uploadProgress: 0, + status: "starting" as const, + }; + // Use setTimeout to ensure the state has been updated before processing + setTimeout(() => readVerifyAndUploadFile(ruleFile, file), 0); + }); }); }; @@ -150,27 +163,33 @@ export const CustomRuleFilesUpload: React.FC = ({ const { uploadFile } = useFileUploader( (file, hubFile) => { - const ruleFile = ruleFileByName(file.name); - if (ruleFile) { - onChangeRuleFile({ - ...ruleFile, - fileId: hubFile?.id, - uploadProgress: 100, - status: "uploaded", - }); - } + // Use a timeout to ensure we get the latest state with contents + setTimeout(() => { + const ruleFile = ruleFileByName(file.name); + if (ruleFile) { + onChangeRuleFile({ + ...ruleFile, + fileId: hubFile?.id, + uploadProgress: 100, + status: "uploaded", + }); + } + }, 0); }, (error, file) => { const msg = getAxiosErrorMessage(error); - const ruleFile = ruleFileByName(file.name); - if (ruleFile) { - onChangeRuleFile({ - ...ruleFile, - loadError: msg, - status: "failed", - }); - } + // Use a timeout to ensure we get the latest state with contents + setTimeout(() => { + const ruleFile = ruleFileByName(file.name); + if (ruleFile) { + onChangeRuleFile({ + ...ruleFile, + loadError: msg, + status: "failed", + }); + } + }, 0); pushNotification({ title: msg, variant: "danger" }); } From c89e34b7a499fedac0152d672d8f8fd3246f239d Mon Sep 17 00:00:00 2001 From: Marek Aufart Date: Tue, 30 Sep 2025 15:33:26 +0200 Subject: [PATCH 2/4] Maybe cleaner fix with per-file context Signed-off-by: Marek Aufart --- .../app/components/CustomRuleFilesUpload.tsx | 117 +++++++++++------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/client/src/app/components/CustomRuleFilesUpload.tsx b/client/src/app/components/CustomRuleFilesUpload.tsx index 9ac2afaa2..0c4d491de 100644 --- a/client/src/app/components/CustomRuleFilesUpload.tsx +++ b/client/src/app/components/CustomRuleFilesUpload.tsx @@ -87,17 +87,16 @@ export const CustomRuleFilesUpload: React.FC = ({ onAddRuleFiles(newRuleFiles); }) .then(() => { - // Trigger the upload process for each file automatically - incomingFiles.forEach((file) => { - const ruleFile = { - fileName: file.name, - fullFile: file, - uploadProgress: 0, - status: "starting" as const, - }; - // Use setTimeout to ensure the state has been updated before processing - setTimeout(() => readVerifyAndUploadFile(ruleFile, file), 0); - }); + // Automatically trigger customFileHandler for each file since PatternFly doesn't do this automatically + // Use setTimeout to ensure state has been updated + setTimeout(() => { + incomingFiles.forEach((file) => { + const ruleFile = ruleFileByName(file.name); + if (ruleFile) { + readVerifyAndUploadFile(ruleFile, file); + } + }); + }, 0); }); }; @@ -151,7 +150,13 @@ export const CustomRuleFilesUpload: React.FC = ({ // Upload the file to hub! // TODO: Provide an onUploadProgress handler so the actual upload can be tracked from 20% to 100% - uploadFile(file, taskgroupId); + const updatedRuleFile = { + ...ruleFile, + uploadProgress: 20, + status: "validated" as const, + contents: fileContents, + }; + uploadFile(file, taskgroupId, updatedRuleFile); } catch (error) { onChangeRuleFile({ ...ruleFile, @@ -162,34 +167,26 @@ export const CustomRuleFilesUpload: React.FC = ({ }; const { uploadFile } = useFileUploader( - (file, hubFile) => { - // Use a timeout to ensure we get the latest state with contents - setTimeout(() => { - const ruleFile = ruleFileByName(file.name); - if (ruleFile) { - onChangeRuleFile({ - ...ruleFile, - fileId: hubFile?.id, - uploadProgress: 100, - status: "uploaded", - }); - } - }, 0); + (file, hubFile, ruleFileContext) => { + if (ruleFileContext) { + onChangeRuleFile({ + ...ruleFileContext, + fileId: hubFile?.id, + uploadProgress: 100, + status: "uploaded", + }); + } }, - (error, file) => { + (error, file, ruleFileContext) => { const msg = getAxiosErrorMessage(error); - // Use a timeout to ensure we get the latest state with contents - setTimeout(() => { - const ruleFile = ruleFileByName(file.name); - if (ruleFile) { - onChangeRuleFile({ - ...ruleFile, - loadError: msg, - status: "failed", - }); - } - }, 0); + if (ruleFileContext) { + onChangeRuleFile({ + ...ruleFileContext, + loadError: msg, + status: "failed", + }); + } pushNotification({ title: msg, variant: "danger" }); } @@ -269,20 +266,52 @@ export const CustomRuleFilesUpload: React.FC = ({ }; function useFileUploader( - onSuccess: (file: File, hubFile?: HubFile) => void, - onError: (e: AxiosError, file: File) => void + onSuccess: ( + file: File, + hubFile?: HubFile, + ruleFileContext?: UploadFile + ) => void, + onError: (e: AxiosError, file: File, ruleFileContext?: UploadFile) => void ) { + // Store file context to pass to callbacks + const fileContextRef = React.useRef(new Map()); + const { mutate: createRuleFile } = useCreateFileMutation( - (hubFile, file) => onSuccess(file, hubFile), - (e, file) => onError(e, file) + (hubFile, file) => { + const ruleFileContext = fileContextRef.current.get(file.name); + onSuccess(file, hubFile, ruleFileContext); + fileContextRef.current.delete(file.name); + }, + (e, file) => { + const ruleFileContext = fileContextRef.current.get(file.name); + onError(e, file, ruleFileContext); + fileContextRef.current.delete(file.name); + } ); const { mutate: uploadTaskgroupFile } = useUploadTaskgroupFileMutation( - (_, { file }) => onSuccess(file), - (e, { file }) => onError(e, file) + (_, { file }) => { + const ruleFileContext = fileContextRef.current.get(file.name); + onSuccess(file, undefined, ruleFileContext); + fileContextRef.current.delete(file.name); + }, + (e, { file }) => { + const ruleFileContext = fileContextRef.current.get(file.name); + onError(e, file, ruleFileContext); + fileContextRef.current.delete(file.name); + } ); - const uploadFile = (file: File, taskgroupId?: number) => { + const uploadFile = ( + file: File, + taskgroupId?: number, + ruleFileContext?: UploadFile + ) => { + // Store the ruleFile context for retrieval in callbacks + if (ruleFileContext) { + fileContextRef.current.set(file.name, ruleFileContext); + } + if (taskgroupId === undefined) { createRuleFile({ file }); } else { From 7bf13b450fb0cfa98ece1eb35f77c16ddf547f05 Mon Sep 17 00:00:00 2001 From: Marek Aufart Date: Fri, 10 Oct 2025 09:35:57 +0200 Subject: [PATCH 3/4] Update client/src/app/components/CustomRuleFilesUpload.tsx Co-authored-by: Scott Dickerson Signed-off-by: Marek Aufart --- client/src/app/components/CustomRuleFilesUpload.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/app/components/CustomRuleFilesUpload.tsx b/client/src/app/components/CustomRuleFilesUpload.tsx index 0c4d491de..399780589 100644 --- a/client/src/app/components/CustomRuleFilesUpload.tsx +++ b/client/src/app/components/CustomRuleFilesUpload.tsx @@ -153,9 +153,10 @@ export const CustomRuleFilesUpload: React.FC = ({ const updatedRuleFile = { ...ruleFile, uploadProgress: 20, - status: "validated" as const, + status: "validated", contents: fileContents, }; + onChangeRuleFile(updatedRuleFile); uploadFile(file, taskgroupId, updatedRuleFile); } catch (error) { onChangeRuleFile({ From ac367e20a0d17fd0fb2d82e1ecd4bf2da308e66a Mon Sep 17 00:00:00 2001 From: Marek Aufart Date: Fri, 10 Oct 2025 09:57:45 +0200 Subject: [PATCH 4/4] Remove redundant upload hook Signed-off-by: Marek Aufart --- .../app/components/CustomRuleFilesUpload.tsx | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/client/src/app/components/CustomRuleFilesUpload.tsx b/client/src/app/components/CustomRuleFilesUpload.tsx index 399780589..c0587480c 100644 --- a/client/src/app/components/CustomRuleFilesUpload.tsx +++ b/client/src/app/components/CustomRuleFilesUpload.tsx @@ -85,18 +85,6 @@ export const CustomRuleFilesUpload: React.FC = ({ status: "starting", })); onAddRuleFiles(newRuleFiles); - }) - .then(() => { - // Automatically trigger customFileHandler for each file since PatternFly doesn't do this automatically - // Use setTimeout to ensure state has been updated - setTimeout(() => { - incomingFiles.forEach((file) => { - const ruleFile = ruleFileByName(file.name); - if (ruleFile) { - readVerifyAndUploadFile(ruleFile, file); - } - }); - }, 0); }); }; @@ -141,16 +129,9 @@ export const CustomRuleFilesUpload: React.FC = ({ ); } } - onChangeRuleFile({ - ...ruleFile, - uploadProgress: 20, - status: "validated", - contents: fileContents, - }); - // Upload the file to hub! // TODO: Provide an onUploadProgress handler so the actual upload can be tracked from 20% to 100% - const updatedRuleFile = { + const updatedRuleFile: UploadFile = { ...ruleFile, uploadProgress: 20, status: "validated",