[FIX] base_import: prevent the list out of range error
When the user uploads a file the length of the list will return 1, but when it tries to retrieve a file which is not in the list or wants to upload another file while the process is ongoing it will throw a IndexError. After this commit, the race condition is satisfied i.e. now the user will not able to upload the file while the uploading is still going on. sentry-3938949468 closes odoo/odoo#120012 X-original-commit: 482e0034e1a5882ea1e0bc4ddb56d8ef5f5a1a92 Signed-off-by: Samuel Degueldre <sad@odoo.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
import { Component, onMounted, useRef } from "@odoo/owl";
|
||||
import { Component, onMounted, useRef, useState } from "@odoo/owl";
|
||||
|
||||
/**
|
||||
* Custom file input
|
||||
@@ -26,6 +26,10 @@ export class FileInput extends Component {
|
||||
setup() {
|
||||
this.http = useService("http");
|
||||
this.fileInputRef = useRef("file-input");
|
||||
this.state = useState({
|
||||
// Disables upload button if currently uploading.
|
||||
isDisable: false,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (this.props.autoOpen) {
|
||||
@@ -70,12 +74,14 @@ export class FileInput extends Component {
|
||||
* - resId: the id of the resModel target instance
|
||||
*/
|
||||
async onFileInputChange() {
|
||||
this.state.isDisable = true;
|
||||
const parsedFileData = await this.uploadFiles(this.httpParams);
|
||||
// When calling onUpload, also pass the files to allow to get data like their names
|
||||
this.props.onUpload(parsedFileData, this.fileInputRef.el ? this.fileInputRef.el.files : []);
|
||||
// Because the input would not trigger this method if the same file name is uploaded,
|
||||
// we must clear the value after handling the upload
|
||||
this.fileInputRef.el.value = null;
|
||||
this.state.isDisable = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="web.FileInput" owl="1">
|
||||
<span class="o_file_input" t-att-class="{ 'd-none': props.hidden }" aria-atomic="true">
|
||||
<span class="o_file_input" t-att-class="{ 'd-none': props.hidden, 'show opacity-50 pe-none': state.isDisable}" aria-atomic="true">
|
||||
<span t-if="!props.hidden" class="o_file_input_trigger" t-on-click.prevent="onTriggerClicked">
|
||||
<t t-slot="default">
|
||||
<button class="btn btn-primary">Choose File</button>
|
||||
@@ -14,6 +14,7 @@
|
||||
t-att-multiple="props.multiUpload"
|
||||
t-att-accept="props.acceptedFileExtensions"
|
||||
t-ref="file-input"
|
||||
t-att-disabled="state.isDisable"
|
||||
t-on-change="onFileInputChange"
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { makeTestEnv } from "@web/../tests/helpers/mock_env";
|
||||
import { editInput, getFixture, mount, patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils";
|
||||
import { editInput, getFixture, mount, patchWithCleanup, triggerEvent, makeDeferred, nextTick } from "@web/../tests/helpers/utils";
|
||||
import { FileInput } from "@web/core/file_input/file_input";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
@@ -138,4 +138,29 @@ QUnit.module("Components", ({ beforeEach }) => {
|
||||
await editInput(target, ".o_file_input input", file);
|
||||
assert.verifySteps(["fake_file.txt"], "file has been uploaded a second time");
|
||||
});
|
||||
|
||||
QUnit.test("Upload button is disabled if attachment upload is not finished", async (assert) => {
|
||||
assert.expect(2);
|
||||
|
||||
const uploadedPromise = makeDeferred();
|
||||
await createFileInput({
|
||||
mockPost: async (route, params) => {
|
||||
if (route === "/web/binary/upload_attachment") {
|
||||
await uploadedPromise;
|
||||
}
|
||||
return "[]";
|
||||
},
|
||||
props: {},
|
||||
});
|
||||
//enable button
|
||||
const input = target.querySelector(".o_file_input input");
|
||||
await triggerEvent(input, null, "change", {}, { skipVisibilityCheck: true });
|
||||
|
||||
//disable button
|
||||
assert.ok(input.disabled, "the upload button should be disabled on upload");
|
||||
|
||||
uploadedPromise.resolve();
|
||||
await nextTick();
|
||||
assert.notOk(input.disabled, "the upload button should be enabled for upload");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user