Skip to content

Commit

Permalink
Merge pull request #4171 from JoinColony/fix/3715-advanced-payments-c…
Browse files Browse the repository at this point in the history
…sv-error

Fix: Advanced payments file upload errors
  • Loading branch information
mmioana authored Jan 30, 2025
2 parents 8b9b89b + 8874caf commit 64b5ee6
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const ColonyAvatarField: FC<ColonyAvatarFieldProps> = ({
handleFileRemove={handleFileRemove}
fileOptions={fileOptions}
errorCode={avatarFileError}
isAvatarUploaded={!!modalValue}
isFileUploaded={!!modalValue}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const FileUploadModal: FC<FileUploadModalProps> = ({
handleFileRemove,
progress,
file,
previouslyAttemptedFileName,
} = useUploadCSVFile(handleFileUpload);

return (
Expand Down Expand Up @@ -99,7 +100,8 @@ const FileUploadModal: FC<FileUploadModalProps> = ({
fileSize: '2MB',
}}
errorCode={fileError}
isAvatarUploaded={!!parsedFileValue}
fallbackFileName={previouslyAttemptedFileName}
isFileUploaded={!!parsedFileValue}
/>
)}
{progress === 100 && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Papa, { type ParseResult } from 'papaparse';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { type FileRejection } from 'react-dropzone';

import { useColonyContext } from '~context/ColonyContext/ColonyContext.ts';
Expand Down Expand Up @@ -73,10 +73,18 @@ export const useUploadCSVFile = (
) => {
const [progress, setProgress] = useState(0);
const [file, setFile] = useState<FileReaderFile | undefined>();
const [previouslyAttemptedFileName, setPreviouslyAttemptedFileName] =
useState<string | undefined>();
const [parsedFileValue, setParsedFileValue] =
useState<ParseResult<ExpenditurePayoutFieldValue> | null>(null);
const [fileError, setFileError] = useState<DropzoneErrors>();

useEffect(() => {
return () => {
setPreviouslyAttemptedFileName(undefined);
};
}, []);

const handleFileRemove = async () => {
setParsedFileValue(null);
setFileError(undefined);
Expand All @@ -98,6 +106,7 @@ export const useUploadCSVFile = (

try {
setFile(uploadedFile);
setPreviouslyAttemptedFileName(uploadedFile.name);

Papa.parse(uploadedFile.file, {
complete: (result: ParseResult<CSVFileItem>) => {
Expand All @@ -110,7 +119,7 @@ export const useUploadCSVFile = (

// Max number of payments is 400, but the format requires two header rows
if (truncatedData.length > 402) {
setError(DropzoneErrors.STRUCTURE);
setError(DropzoneErrors.CONTENT_TOO_LARGE);
return;
}

Expand Down Expand Up @@ -168,6 +177,7 @@ export const useUploadCSVFile = (
handleFileRemove,
progress,
file,
previouslyAttemptedFileName,
};
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/v5/common/AvatarUploader/AvatarUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const AvatarUploader: FC<AvatarUploaderProps & UseAvatarUploaderProps> = ({
handleFileReject,
handleFileRemove,
errorCode: uploadAvatarError,
isAvatarUploaded,
isFileUploaded: isAvatarUploaded,
isProgressContentVisible: showProgress,
SuccessComponent,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { useIntl } from 'react-intl';

import { TextButton } from '~v5/shared/Button/index.ts';

import { type ErrorContentProps } from '../types.ts';
import {
type ErrorContentProps,
type FileUploadMessageValues,
} from '../types.ts';
import { DropzoneErrors, getErrorMessage } from '../utils.ts';

const displayName = 'v5.common.AvatarUploader.partials.ErrorContent';
Expand All @@ -14,6 +17,7 @@ const ErrorContent: FC<ErrorContentProps> = ({
handleFileRemove,
open,
processedFile,
fileOptions,
}) => {
const { formatMessage } = useIntl();

Expand All @@ -34,7 +38,10 @@ const ErrorContent: FC<ErrorContentProps> = ({
<div className="flex w-full flex-col gap-1">
<div className="items-top flex justify-between gap-2">
<span className=" text-left text-negative-400 text-1">
{formatMessage(errorMessage)}
{formatMessage(
errorMessage,
fileOptions as FileUploadMessageValues,
)}
</span>
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const FileUpload: FC<FileUploadProps> = ({
handleFileReject,
handleFileRemove,
errorCode,
isAvatarUploaded,
fallbackFileName,
isFileUploaded,
isProgressContentVisible,
isSimplified,
fileOptions,
Expand Down Expand Up @@ -43,7 +44,7 @@ const FileUpload: FC<FileUploadProps> = ({

const shouldShowDefaultContent =
(showDefault && !errorCode) ||
(!isAvatarUploaded && !errorCode && !isProgressContentVisible);
(!isFileUploaded && !errorCode && !isProgressContentVisible);

const shouldShowSuccessContent = !shouldShowDefaultContent && !errorCode;

Expand All @@ -70,7 +71,8 @@ const FileUpload: FC<FileUploadProps> = ({
errorCode={errorCode}
handleFileRemove={handleFileRemove}
open={open}
processedFile={processedFiles?.[0]?.name}
processedFile={processedFiles?.[0]?.name ?? fallbackFileName}
fileOptions={fileOptions}
/>
);

Expand Down
13 changes: 11 additions & 2 deletions src/components/v5/common/AvatarUploader/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export type SuccessContentProps = Pick<
export type HandleFileAccept = (file: FileReaderFile) => void;

export interface ErrorContentProps
extends Pick<FileUploadProps, 'handleFileRemove' | 'errorCode'> {
extends Pick<
FileUploadProps,
'handleFileRemove' | 'errorCode' | 'fileOptions'
> {
processedFile?: string;
open: () => void;
}
Expand All @@ -27,10 +30,16 @@ export interface FileUploadOptions {
fileDimension: string;
}

export interface FileUploadMessageValues extends FileUploadOptions {
[key: string]: any;
}

export interface FileUploadProps {
dropzoneOptions: DropzoneOptions;
isAvatarUploaded: boolean;
isFileUploaded: boolean;
errorCode?: DropzoneErrors;
// Used to display the filename if the file is rejected during the upload handler but not by dropzone.
fallbackFileName?: string;
handleFileAccept: HandleFileAccept;
handleFileReject?: (
fileRejections: FileRejection[],
Expand Down
10 changes: 9 additions & 1 deletion src/components/v5/common/AvatarUploader/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const MSG = defineMessages({
id: `${displayName}.customError`,
defaultMessage: 'Upload failed, please try again',
},
contentTooLarge: {
id: `${displayName}.contentTooLarge`,
defaultMessage: 'File exceeds {fileDimension}. Reduce and try again',
},
wrongStructure: {
id: `${displayName}.wrongStructure`,
defaultMessage: 'File structure is incorrect, please try again',
Expand All @@ -40,7 +44,7 @@ const MSG = defineMessages({
},
fileMinDimensionsError: {
id: `${displayName}.fileMinDimensionsError`,
defaultMessage: 'Image dimensions should be at least 120x120px',
defaultMessage: 'Image dimensions should be at least {fileDimension}',
},
});

Expand All @@ -54,6 +58,7 @@ export enum DropzoneErrors {
TOO_LARGE = 'file-too-large',
// TOO_SMALL = 'file-too-small', // wire in as needed
// TOO_MANY = 'too-many-files',
CONTENT_TOO_LARGE = 'content-too-large',
STRUCTURE = 'wrong-structure',
CUSTOM = 'custom-error',
DEFAULT = 'default',
Expand All @@ -77,6 +82,9 @@ export const getErrorMessage = (errorCode: DropzoneErrors) => {
case DropzoneErrors.CUSTOM: {
return MSG.customError;
}
case DropzoneErrors.CONTENT_TOO_LARGE: {
return MSG.contentTooLarge;
}
case DropzoneErrors.STRUCTURE: {
return MSG.wrongStructure;
}
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1866,7 +1866,7 @@
"milestoneModal.paymentCreatorDescription": "This will use your temporary permissions as the payment creator to immediately make the selected milestone payments.",
"milestoneModal.multiSig": "This will start the approval process using multi-sig permissions to make the decision, for making the selected milestone payments.",
"fileUploadModal.title": "Upload CSV",
"fileUploadModal.description": "Bulk upload recipients using a CSV. Use the template to ensure the correct structure, be sure to remove the sample data.",
"fileUploadModal.description": "Bulk upload up to 400 recipients using a CSV. Use the template to ensure the correct structure, be sure to remove the sample data.",
"fileUploadModal.uploadFile": "Upload CSV File",
"fileUploadModal.downloadTemplate": "Download .CSV template",
"fileUploadModal.warningImportant": "Important: ",
Expand Down

0 comments on commit 64b5ee6

Please sign in to comment.