benwinding / react-admin-import-csv

A csv file import button for react-admin

Home Page:https://benwinding.github.io/react-admin-import-csv

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Notification update - translation not working properly %{fname}

peter-jerry-ye opened this issue · comments

According to this answer, the setState won't change the function immediately, thus we can see that in the notification, the translation does not work, because the state remains null.
截屏2020-11-20 下午3 59 02

Thanks for reporting and fixing the issue @peter-jerry-ye,
Should be deployed in version 1.0.6
Cheers,
Ben

Thanks for reporting and fixing the issue @peter-jerry-ye,
Should be deployed in version 1.0.6
Cheers,
Ben

Sorry for the confusion, but the pull request wasn't aimed for this issue. The pull request was aimed to allow async preprocess of csv file, but this issue is something else.

Ahh okay, I'll have a look at this in the next few days 👍

Peek 2020-11-21 18-39

Translation seems to work with Demo here: https://benwinding.github.io/react-admin-import-csv/

Can you show me the configuration you had to reproduce that?

Found the exact issue.

  • The rendering and state doesn't seem to affect the translations.
  • It seems to be the translation library not interpreting Chinese correctly.
    image
  • I replaced a Chinese, translation with an English one in src/i18n/zh.ts and the English one worked correctly.
    image
  • Spanish translations have the same issue 😢
    image

Found the issue, turns out was a simple uni-code character mismatch, from copying from Google Translate, it didn't use the correct % sign!!
image
Should be working now, that was a silly bug 😆

Thank you for your great work!

But unfortunately one problem still remains: the problem with the notification.
I've just tested with your most recently deployed app. If you delete everything and reimport from file, i.e. import without collision, you'll see that the notification shows 'Imported', without the name of the file. On my side it'll be '导入的%{fname}'. But if you import a file with collision, the notification displays correctly the name of the file.
I still believe it's relevant to what I've mentioned at the beginning.

Hi @peter-jerry-ye,
Wow this thing is difficult to fix!

  • So I cannot replicate the issue you're describing, can you send a video of the issue and exact steps to reproduce it?
    Peek 2020-11-22 20-42
  • Also I've updated some dependencies, maybe that fixed it?
  • I'm still not sure that it's a state related problem, as the translation and notify are both synchronously executed:
    const notify = useNotify();
    const handleClose = () => {
    resetVars();
    notify(translate("csv.dialogImport.alertClose", { fname: fileName }));
    refresh();
    };
  • It's more likely that the fname variable is null for some reason, but I'm not sure how to reproduce the error.
  • You can make a PR to fix the issue if you're able to find it...
    Thanks,
    Ben

@benwinding You've already replicated the issue. I should correct my description: On my side it'll be '导入的' without the file name, i.e. fname is null. The fact I saw %{fname} was due to the previous bug.

I'm not sure what you mean by you don't know how to reproduce the error: you've already done that.

What I've found was that if you add console.log(fileName) after line 98 of main-csv-button.tsx, you'll see that fileName remains empty, which is why I said it should be related to useState.

In fact, you should've noticed it yourself, as you've placed resetVars() on line 146 which setFileName(''); before the fileName is used on line 147, while you can still have the file name displayed normally in the case there's a conflict.

I'm not sure if my description is clear enough. I would love to make a PR to fix it, just as I've done last friday. In fact a simple solution is convert fname from a state to a simple variable passed along all function, but I might not be free during the week.

Ahhh, okay I think I understand the issue now. ${fname} is empty in certain conditions right?. Well, I think it's finally fixed!

Peek 2020-11-22 22-59

You were correct it was due to the setState being used in an asynchronous function. This kind of breaks the rules of react hooks, and is better suited to the useEffect hook. The implementation has been changed to use the File object as the trigger to cause the rest of the effects, via setFile(file).

const onFileAdded = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files && e.target.files[0];
setFile(file);
};

const [file, setFile] = React.useState<File | null>();
const fileName = (file && file.name) + "";
React.useEffect(() => {
let mounted = true;
if (!file) {
setOpen(false);
return;
}
setOpen(true);
async function processCSV(): Promise<[any[], boolean]> {
// Is valid csv
if (!file) {
throw new Error("File not processed from input field");
}
logger.log("Parsing CSV file");
const csvItems = await GetCSVItems(logging, translate, file, parseConfig);
mounted && setValues(csvItems);
// Does CSV pass user validation
logger.log("Validating CSV file");
await CheckCSVValidation(logging, translate, csvItems, validateRow);
// Are there any import overwrites?
logger.log("Checking rows to import");
const collidingIds = await GetIdsColliding(
logging,
translate,
dataProvider,
csvItems,
resourceName
);
mounted && setIdsConflicting(collidingIds);
const hasCollidingIds = !!collidingIds.length;
logger.log("Has colliding ids?", { hasCollidingIds, collidingIds });
if (!hasCollidingIds) {
return [csvItems, hasCollidingIds];
}
// Ask Replace X Rows? Skip these rows? Decied For Each?
const collindingIdsSet = new Set(collidingIds.map((id) => id));
const csvItemsNotColliding = csvItems.filter(
(item) => !collindingIdsSet.has(item.id)
);
logger.log("Importing items which arent colliding", {
csvItemsNotColliding,
});
return [csvItemsNotColliding, hasCollidingIds];
}
processCSV()
.then(async ([csvItems, hasCollidingIds]) => {
await createRows(csvItems);
mounted && !hasCollidingIds && handleClose();
})
.catch((error) => {
mounted && resetVars();
logger.error(error);
});
return () => {
mounted = false;
};
}, [file]);

Let me know if this works!
Cheers,
Ben

Well done! The issue is fixed. Thank you very much.