diff --git a/src/components/file-step/FileSelector.scss b/src/components/file-step/FileSelector.scss index 057e837..36bbd62 100644 --- a/src/components/file-step/FileSelector.scss +++ b/src/components/file-step/FileSelector.scss @@ -9,6 +9,10 @@ color: $textColor; cursor: pointer; + &--error { + color: $errorTextColor; + } + &[data-active='true'] { background: darken($fillColor, 10%); transition: background 0.1s ease-out; diff --git a/src/components/file-step/FileSelector.tsx b/src/components/file-step/FileSelector.tsx index 7eebd37..a62ba62 100644 --- a/src/components/file-step/FileSelector.tsx +++ b/src/components/file-step/FileSelector.tsx @@ -1,44 +1,69 @@ -import React, { useCallback, useRef } from 'react'; +import React, { useCallback, useRef, useState } from 'react'; import { useDropzone } from 'react-dropzone'; import { useLocale } from '../../locale/LocaleContext'; import './FileSelector.scss'; -export const FileSelector: React.FC<{ onSelected: (file: File) => void }> = ({ +export const FileSelector: React.FC<{ + onSelected: (file: File) => void +}> = ({ onSelected }) => { - const onSelectedRef = useRef(onSelected); - onSelectedRef.current = onSelected; + const onSelectedRef = useRef(onSelected); + onSelectedRef.current = onSelected; + const [unsupportedFileFormat, setUnsupportedFileFormat] = useState(false) + const supportedFileFormats = ["text/csv", "text/plain"] - const dropHandler = useCallback((acceptedFiles: File[]) => { - // silently ignore if nothing to do - if (acceptedFiles.length < 1) { - return; + const dropHandler = useCallback((acceptedFiles: File[]) => { + // silently ignore if nothing to do + if (acceptedFiles.length < 1) { + return; + } + + const file = acceptedFiles[0]; + if (!supportedFileFormats.includes(file.type)) return setUnsupportedFileFormat(true) + onSelectedRef.current(file); + }, []); + + const { getRootProps, getInputProps, isDragActive } = useDropzone({ + onDrop: dropHandler + }); + + const l10n = useLocale('fileStep'); + + const errorBlock = () => { + return ( +
+ {l10n.unsupportedFileFormatError}. {l10n.activeDragDropPrompt} +
+ ) } - const file = acceptedFiles[0]; - onSelectedRef.current(file); - }, []); - - const { getRootProps, getInputProps, isDragActive } = useDropzone({ - onDrop: dropHandler - }); - - const l10n = useLocale('fileStep'); - - return ( -
- - - {isDragActive ? ( - {l10n.activeDragDropPrompt} - ) : ( - {l10n.initialDragDropPrompt} - )} -
- ); -}; + return ( +
+ + + {isDragActive ? ( + + { + unsupportedFileFormat ? + errorBlock() : + l10n.activeDragDropPrompt + } + + ) : ( + + { + unsupportedFileFormat ? + errorBlock() : + l10n.initialDragDropPrompt + } + + )} +
+ ); + }; diff --git a/src/locale/index.ts b/src/locale/index.ts index c2fa355..3b852be 100644 --- a/src/locale/index.ts +++ b/src/locale/index.ts @@ -11,6 +11,7 @@ export interface ImporterLocale { getImportError: (message: string) => string; getDataFormatError: (message: string) => string; + unsupportedFileFormatError: string; goBackButton: string; nextButton: string; @@ -71,6 +72,7 @@ export const enUS: ImporterLocale = { getImportError: (message) => `Import error: ${message}`, getDataFormatError: (message) => `Please check data formatting: ${message}`, + unsupportedFileFormatError: 'File format not supported', goBackButton: 'Go Back', nextButton: 'Choose columns', @@ -133,6 +135,7 @@ export const deDE: ImporterLocale = { getImportError: (message) => `Fehler beim Import: ${message}`, getDataFormatError: (message: string) => `Bitte Datenformat überprüfen: ${message}`, + unsupportedFileFormatError : 'Dateiformat nicht unterstützt', goBackButton: 'Zurück', rawFileContentsHeading: 'Originaler Datei-Inhalt', @@ -193,6 +196,7 @@ export const itIT: ImporterLocale = { getImportError: (message) => `Errore durante l'importazione: ${message}`, getDataFormatError: (message) => `Si prega di controllare il formato dei dati: ${message}`, + unsupportedFileFormatError : 'Formato file non supportato', goBackButton: 'Torna indietro', nextButton: 'Seleziona le colonne', @@ -253,6 +257,7 @@ export const ptBR: ImporterLocale = { getImportError: (message) => `Erro ao importar: ${message}`, getDataFormatError: (message) => `Por favor confira a formatação dos dados: ${message}`, + unsupportedFileFormatError : 'Formato de arquivo não suportado', goBackButton: 'Voltar', nextButton: 'Escolher Colunas', @@ -314,6 +319,7 @@ export const daDK: ImporterLocale = { getImportError: (message) => `Import-fejl: ${message}`, getDataFormatError: (message) => `Kontrollér venligst data-formatering: ${message}`, + unsupportedFileFormatError : 'Filformat understøttes ikke', goBackButton: "Gå tilbage", nextButton: "Vælg kolonner", @@ -375,6 +381,7 @@ export const trTR: ImporterLocale = { getImportError: (message) => `Import hatası: ${message}`, getDataFormatError: (message) => `Lütfen veri formatını kontrol edin: ${message}`, + unsupportedFileFormatError : 'Dosya formatı desteklenmiyor', goBackButton: "Geri", nextButton: "Kolonları Seç", diff --git a/test/basics.test.ts b/test/basics.test.ts index 450bc36..8716df2 100644 --- a/test/basics.test.ts +++ b/test/basics.test.ts @@ -62,6 +62,21 @@ describe('importer basics', () => { expect(await fileInput.getAttribute('type')).to.equal('file'); }); + it('with unsupported file selected', async () => { + const filePath = path.resolve(__dirname, './fixtures/img.png'); + + const fileInput = await getDriver().findElement(By.xpath('//input')); + await fileInput.sendKeys(filePath); + + await getDriver().wait( + until.elementLocated(By.xpath('//*[contains(., "File format not supported")]')), + 300 // extra time + ); + + const errorBlock = await getDriver().findElement(By.xpath('//*[contains(., "File format not supported")]')) + expect(await errorBlock.getText()).to.include("File format not supported") + }) + describe('with file selected', () => { beforeEach(async () => { const filePath = path.resolve(__dirname, './fixtures/simple.csv'); diff --git a/test/fixtures/img.png b/test/fixtures/img.png new file mode 100644 index 0000000..9490ffc Binary files /dev/null and b/test/fixtures/img.png differ