diff --git a/public/locales/bg/validation.json b/public/locales/bg/validation.json index d341eb735..26d075d9a 100644 --- a/public/locales/bg/validation.json +++ b/public/locales/bg/validation.json @@ -22,5 +22,6 @@ "payment-reference": "Невалиден формат на кода за плащане", "eik-invalid": "Невалидно ЕИК", "help-us-improve": "Съгласявам се да се свържете с мен за подобрение на платформата.", - "positive-amount": "Сумата трябва да е положително число." + "positive-amount": "Сумата трябва да е положително число.", + "invalid-file": "Невалиден файл." } diff --git a/public/locales/en/validation.json b/public/locales/en/validation.json index 5225bf637..e3584afce 100644 --- a/public/locales/en/validation.json +++ b/public/locales/en/validation.json @@ -22,5 +22,6 @@ "payment-reference": "Invalid payment code format", "eik-invalid": "Invalid EIK", "help-us-improve": "I agree to be contacted to help improve the platform.", - "positive-amount": "The amount must be a positive number." + "positive-amount": "The amount must be a positive number.", + "invalid-file": "Invalid file." } diff --git a/src/components/admin/campaigns/grid/CreateForm.tsx b/src/components/admin/campaigns/grid/CreateForm.tsx index 5432a7ae0..f0c87da97 100644 --- a/src/components/admin/campaigns/grid/CreateForm.tsx +++ b/src/components/admin/campaigns/grid/CreateForm.tsx @@ -25,7 +25,13 @@ const FormRichTextField = dynamic(() => import('components/common/form/FormRichT ssr: false, }) -import { ApiErrors, handleUniqueViolation, isAxiosError, matchValidator } from 'service/apiErrors' +import { + ApiErrors, + handleFileUploadError, + handleUniqueViolation, + isAxiosError, + matchValidator, +} from 'service/apiErrors' import { useCreateCampaign, useUploadCampaignFiles } from 'service/campaign' import { CampaignFileRole, @@ -137,6 +143,7 @@ export default function CampaignForm({ initialValues = defaults }: CampaignFormP UploadCampaignFiles >({ mutationFn: useUploadCampaignFiles(), + onError: (error) => handleFileUploadError(error, t), }) const onSubmit = async ( diff --git a/src/components/admin/campaigns/grid/EditForm.tsx b/src/components/admin/campaigns/grid/EditForm.tsx index 44a4772f1..1a4735cd0 100644 --- a/src/components/admin/campaigns/grid/EditForm.tsx +++ b/src/components/admin/campaigns/grid/EditForm.tsx @@ -23,7 +23,13 @@ const FormRichTextField = dynamic(() => import('components/common/form/FormRichT ssr: false, }) -import { ApiErrors, handleUniqueViolation, isAxiosError, matchValidator } from 'service/apiErrors' +import { + ApiErrors, + handleFileUploadError, + handleUniqueViolation, + isAxiosError, + matchValidator, +} from 'service/apiErrors' import { CampaignResponse, CampaignInput, @@ -167,7 +173,7 @@ export default function EditForm({ campaign }: { campaign: AdminSingleCampaignRe UploadCampaignFiles >({ mutationFn: useUploadCampaignFiles(), - onError: () => AlertStore.show(t('common:alerts.error'), 'error'), + onError: (error) => handleFileUploadError(error, t), onSuccess: () => { //invalidate query for getting new values queryClient.invalidateQueries([endpoints.campaign.viewCampaignById(campaign.id).url]) diff --git a/src/components/admin/donations/AddBankTransactionsFileForm.tsx b/src/components/admin/donations/AddBankTransactionsFileForm.tsx index cac392ceb..2a6939f57 100644 --- a/src/components/admin/donations/AddBankTransactionsFileForm.tsx +++ b/src/components/admin/donations/AddBankTransactionsFileForm.tsx @@ -22,7 +22,7 @@ import FileUpload from 'components/common/file-upload/FileUpload' import GenericForm from 'components/common/form/GenericForm' import SubmitButton from 'components/common/form/SubmitButton' import FormTextField from 'components/common/form/FormTextField' -import { ApiErrors, isAxiosError, matchValidator } from 'service/apiErrors' +import { ApiErrors, handleFileUploadError, isAxiosError, matchValidator } from 'service/apiErrors' import { BankTransactionsFileType, FileType, @@ -72,7 +72,7 @@ export default function BankTransactionsFileForm({ UploadBankTransactionsFiles >({ mutationFn: useUploadBankTransactionsFiles(), - onError: () => AlertStore.show(t('common:alerts.error'), 'error'), + onError: (error) => handleFileUploadError(error, t), onSuccess: () => AlertStore.show(t('common:alerts.message-sent'), 'success'), }) diff --git a/src/components/admin/irregularity/admin/grid/CreateForm.tsx b/src/components/admin/irregularity/admin/grid/CreateForm.tsx index 0dc7c6e33..b8055301d 100644 --- a/src/components/admin/irregularity/admin/grid/CreateForm.tsx +++ b/src/components/admin/irregularity/admin/grid/CreateForm.tsx @@ -12,7 +12,7 @@ import { CampaignResponse } from 'gql/campaigns' import { Button, Grid } from '@mui/material' -import { ApiErrors } from 'service/apiErrors' +import { ApiErrors, handleFileUploadError } from 'service/apiErrors' import { createIrregularity, uploadIrregularityFiles } from 'service/irregularity' import { AlertStore } from 'stores/AlertStore' import { routes } from 'common/routes' @@ -90,6 +90,7 @@ export default function CreateForm({ campaigns, person }: Props) { IrregularityInput >({ mutationFn: createIrregularity, + onError: () => AlertStore.show(t('common:alerts.error'), 'error'), }) const fileUploadMutation = useMutation< @@ -98,6 +99,7 @@ export default function CreateForm({ campaigns, person }: Props) { UploadIrregularityFiles >({ mutationFn: uploadIrregularityFiles(), + onError: (error) => handleFileUploadError(error, t), }) const onSubmit = async (values: IrregularityInput) => { @@ -122,7 +124,7 @@ export default function CreateForm({ campaigns, person }: Props) { AlertStore.show(t('common:alerts.message-sent'), 'success') router.push(routes.admin.irregularity.index) } catch (error) { - AlertStore.show(t('common:alerts.error'), 'error') + console.error(error) } } diff --git a/src/components/admin/irregularity/admin/grid/EditForm.tsx b/src/components/admin/irregularity/admin/grid/EditForm.tsx index ec6c0ad69..8903d681a 100644 --- a/src/components/admin/irregularity/admin/grid/EditForm.tsx +++ b/src/components/admin/irregularity/admin/grid/EditForm.tsx @@ -10,7 +10,7 @@ import { AxiosError, AxiosResponse } from 'axios' import { useMutation, useQueryClient } from '@tanstack/react-query' -import { ApiErrors } from 'service/apiErrors' +import { ApiErrors, handleFileUploadError } from 'service/apiErrors' import { endpoints } from 'service/apiEndpoints' import { editIrregularity, uploadIrregularityFiles } from 'service/irregularity' @@ -98,6 +98,7 @@ export default function EditForm({ campaigns, irregularity, irregularityFiles }: IrregularityEditInput >({ mutationFn: editIrregularity(irregularity.id), + onError: () => AlertStore.show(t('common:alerts.error'), 'error'), }) const fileUploadMutation = useMutation< @@ -106,6 +107,7 @@ export default function EditForm({ campaigns, irregularity, irregularityFiles }: UploadIrregularityFiles >({ mutationFn: uploadIrregularityFiles(), + onError: (error) => handleFileUploadError(error, t), }) const onSubmit = async (values: IrregularityEditInput) => { @@ -132,7 +134,7 @@ export default function EditForm({ campaigns, irregularity, irregularityFiles }: queryClient.invalidateQueries([endpoints.irregularity.viewIrregularity(irregularity.id).url]) router.push(routes.admin.irregularity.index) } catch (error) { - AlertStore.show(t('common:alerts.error'), 'error') + console.error(error) } } diff --git a/src/components/client/campaign-application/steps/CampaignApplicationDetails.tsx b/src/components/client/campaign-application/steps/CampaignApplicationDetails.tsx index b5454057c..10cd3dba6 100644 --- a/src/components/client/campaign-application/steps/CampaignApplicationDetails.tsx +++ b/src/components/client/campaign-application/steps/CampaignApplicationDetails.tsx @@ -66,7 +66,6 @@ export default function CampaignApplicationDetails({ files, setFiles }: Props) { setFiles((prevFiles) => [...prevFiles, ...newFiles]) setFieldValue('applicationDetails.documents', newFiles) }} - accept="text/plain,application/json,application/pdf,image/png,image/jpeg,application/xml,text/xml,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" /> {touched.applicationDetails?.documents && errors.applicationDetails?.documents && ( {t('steps.details.documents-hint')} diff --git a/src/components/client/campaign-expenses/Form.tsx b/src/components/client/campaign-expenses/Form.tsx index 289f7f750..3138dcf8e 100644 --- a/src/components/client/campaign-expenses/Form.tsx +++ b/src/components/client/campaign-expenses/Form.tsx @@ -21,7 +21,7 @@ import FormTextField from 'components/common/form/FormTextField' import { Checkbox } from '@mui/material' import { useCreateExpense, useEditExpense } from 'service/expense' -import { ApiErrors, isAxiosError, matchValidator } from 'service/apiErrors' +import { ApiErrors, handleFileUploadError, isAxiosError, matchValidator } from 'service/apiErrors' import { ExpenseInput, ExpenseResponse, ExpenseStatus, ExpenseType } from 'gql/expenses' import FileUpload from 'components/common/file-upload/FileUpload' @@ -66,7 +66,7 @@ export default function Form() { UploadExpenseFile >({ mutationFn: useUploadExpenseFiles(), - onError: () => AlertStore.show(t('common:alerts.error'), 'error'), + onError: (error) => handleFileUploadError(error, t), }) let data: ExpenseResponse | undefined diff --git a/src/components/client/campaign-news/secured/CreateForm.tsx b/src/components/client/campaign-news/secured/CreateForm.tsx index 58ca10d8e..595436483 100644 --- a/src/components/client/campaign-news/secured/CreateForm.tsx +++ b/src/components/client/campaign-news/secured/CreateForm.tsx @@ -22,7 +22,13 @@ const FormRichTextField = dynamic(() => import('components/common/form/FormRichT ssr: false, }) -import { ApiErrors, handleUniqueViolation, isAxiosError, matchValidator } from 'service/apiErrors' +import { + ApiErrors, + handleFileUploadError, + handleUniqueViolation, + isAxiosError, + matchValidator, +} from 'service/apiErrors' import { useUploadCampaignNewsFiles } from 'service/campaign-news' import { CampaignFileRole, @@ -111,6 +117,7 @@ export default function CreateForm({ campaignId = '', isAdmin = true }: Campaign UploadCampaignNewsFiles >({ mutationFn: useUploadCampaignNewsFiles(), + onError: (error) => handleFileUploadError(error, t), }) const onSubmit = async ( diff --git a/src/components/client/campaign-news/secured/EditForm.tsx b/src/components/client/campaign-news/secured/EditForm.tsx index bed31df12..f23bdb421 100644 --- a/src/components/client/campaign-news/secured/EditForm.tsx +++ b/src/components/client/campaign-news/secured/EditForm.tsx @@ -27,7 +27,13 @@ const FormRichTextField = dynamic(() => import('components/common/form/FormRichT ssr: false, }) -import { ApiErrors, handleUniqueViolation, isAxiosError, matchValidator } from 'service/apiErrors' +import { + ApiErrors, + handleFileUploadError, + handleUniqueViolation, + isAxiosError, + matchValidator, +} from 'service/apiErrors' import { CampaignUploadImage } from 'gql/campaigns' import { ArticleStatus } from 'components/admin/campaign-news/helpers/article-status.enum' import ArticleStatusSelect from 'components/admin/campaign-news/ArticleStatusSelect' @@ -123,7 +129,7 @@ export default function EditForm({ article, campaignId = '', isAdmin = true }: P UploadCampaignNewsFiles >({ mutationFn: useUploadCampaignNewsFiles(), - onError: () => AlertStore.show(t('common:alerts.error'), 'error'), + onError: (error) => handleFileUploadError(error, t), onSuccess: () => { //invalidate query for getting new values queryClient.invalidateQueries([endpoints.campaignNews.viewNewsArticleById(article.id).url]) diff --git a/src/components/client/campaigns/CampaignForm.tsx b/src/components/client/campaigns/CampaignForm.tsx index 6172f09a6..b962b5331 100644 --- a/src/components/client/campaigns/CampaignForm.tsx +++ b/src/components/client/campaigns/CampaignForm.tsx @@ -25,7 +25,7 @@ import { UploadCampaignFiles, } from 'components/common/campaign-file/roles' import AcceptTermsField from 'components/common/form/AcceptTermsField' -import { ApiErrors, isAxiosError, matchValidator } from 'service/apiErrors' +import { ApiErrors, handleFileUploadError, isAxiosError, matchValidator } from 'service/apiErrors' import { useCreateCampaign, useUploadCampaignFiles } from 'service/campaign' import { CampaignResponse, @@ -114,6 +114,7 @@ export default function CampaignForm({ initialValues = defaults }: CampaignFormP UploadCampaignFiles >({ mutationFn: useUploadCampaignFiles(), + onError: (error) => handleFileUploadError(error, t), }) const onSubmit = async ( diff --git a/src/components/client/irregularity/helpers/IrregularityForm.tsx b/src/components/client/irregularity/helpers/IrregularityForm.tsx index edb651695..87a37abea 100644 --- a/src/components/client/irregularity/helpers/IrregularityForm.tsx +++ b/src/components/client/irregularity/helpers/IrregularityForm.tsx @@ -11,7 +11,7 @@ import { FormikHelpers, FormikProps } from 'formik' import { StepLabel, Grid } from '@mui/material' -import { ApiErrors, isAxiosError, matchValidator } from 'service/apiErrors' +import { ApiErrors, handleFileUploadError, isAxiosError, matchValidator } from 'service/apiErrors' import { createIrregularity, uploadIrregularityFiles } from 'service/irregularity' import { @@ -116,6 +116,7 @@ export default function IrregularityForm({ campaign, person }: Props) { UploadIrregularityFiles >({ mutationFn: uploadIrregularityFiles(), + onError: (error) => handleFileUploadError(error, t), }) const handleBack = () => { diff --git a/src/components/common/file-upload/FileUpload.tsx b/src/components/common/file-upload/FileUpload.tsx index 9078029c2..76e2e033c 100644 --- a/src/components/common/file-upload/FileUpload.tsx +++ b/src/components/common/file-upload/FileUpload.tsx @@ -5,21 +5,38 @@ const Input = styled('input')({ display: 'none', }) +const mimeAllowlistStr = [ + 'text/plain', + 'application/json', + 'application/pdf', + 'image/png', + 'image/jpeg', + 'application/xml', + 'text/xml', + 'application/msword', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', +].join(',') + function FileUpload({ onUpload, buttonLabel, + accept, ...rest }: { onUpload: (files: File[]) => void buttonLabel: string - accept?: string + accept?: string[] }) { + const acceptStr = accept ? accept.join(',') : mimeAllowlistStr + return (