Before this commit, when clicking on "Attach files" in discuss composer, then removing it, it was not possible to upload the same file again. This happens because file input of file uploader relies on `change` from the input. The `input.value` contains the filepath, so if we upload the exact same file without clearing the value, the value will be unchanged and it won't trigger uploading as a result. This commit fixes the issue by clearing the input just after the file has been uploaded, so that we can upload the same file. Cannot reproduce bug in QUnit tests because `inputFile` helper programmatically always trigger "change" on input file. closes odoo/odoo#117704 Signed-off-by: Luca Vitali <luvi@odoo.com>
93 lines
3.0 KiB
JavaScript
93 lines
3.0 KiB
JavaScript
/** @odoo-module **/
|
|
|
|
import { useService } from "@web/core/utils/hooks";
|
|
import { sprintf } from "@web/core/utils/strings";
|
|
import { getDataURLFromFile } from "@web/core/utils/urls";
|
|
import { session } from "@web/session";
|
|
import { formatFloat } from "./formatters";
|
|
|
|
import { Component, useRef, useState } from "@odoo/owl";
|
|
|
|
const DEFAULT_MAX_FILE_SIZE = 128 * 1024 * 1024;
|
|
|
|
export class FileUploader extends Component {
|
|
setup() {
|
|
this.notification = useService("notification");
|
|
this.fileInputRef = useRef("fileInput");
|
|
this.state = useState({
|
|
isUploading: false,
|
|
});
|
|
}
|
|
|
|
get maxUploadSize() {
|
|
return session.max_file_upload_size || DEFAULT_MAX_FILE_SIZE;
|
|
}
|
|
/**
|
|
* @param {Event} ev
|
|
*/
|
|
async onFileChange(ev) {
|
|
if (!ev.target.files.length) {
|
|
return;
|
|
}
|
|
for (const file of ev.target.files) {
|
|
if (file.size > this.maxUploadSize) {
|
|
this.notification.add(
|
|
sprintf(
|
|
this.env._t("The selected file exceed the maximum file size of %s."),
|
|
formatFloat(this.maxUploadSize, { humanReadable: true })
|
|
),
|
|
{
|
|
title: this.env._t("File upload"),
|
|
type: "danger",
|
|
}
|
|
);
|
|
}
|
|
this.state.isUploading = true;
|
|
const data = await getDataURLFromFile(file);
|
|
if (!file.size) {
|
|
console.warn(`Error while uploading file : ${file.name}`);
|
|
this.notification.add(
|
|
this.env._t("There was a problem while uploading your file."),
|
|
{
|
|
type: "danger",
|
|
}
|
|
);
|
|
}
|
|
await this.props.onUploaded({
|
|
name: file.name,
|
|
size: file.size,
|
|
type: file.type,
|
|
data: data.split(",")[1],
|
|
objectUrl: file.type === "application/pdf" ? URL.createObjectURL(file) : null,
|
|
});
|
|
this.state.isUploading = false;
|
|
}
|
|
ev.target.value = null;
|
|
if (this.props.multiUpload && this.props.onUploadComplete) {
|
|
this.props.onUploadComplete({});
|
|
}
|
|
}
|
|
|
|
async onSelectFileButtonClick(ev) {
|
|
if (this.props.onClick) {
|
|
const ok = await this.props.onClick(ev);
|
|
if (ok !== undefined && !ok) {
|
|
return;
|
|
}
|
|
}
|
|
this.fileInputRef.el.click();
|
|
}
|
|
}
|
|
|
|
FileUploader.template = "web.FileUploader";
|
|
FileUploader.props = {
|
|
onClick: { type: Function, optional: true },
|
|
onUploaded: Function,
|
|
onUploadComplete: { type: Function, optional: true },
|
|
multiUpload: { type: Boolean, optional: true },
|
|
inputName: { type: String, optional: true },
|
|
fileUploadClass: { type: String, optional: true },
|
|
acceptedFileExtensions: { type: String, optional: true },
|
|
slots: { type: Object, optional: true },
|
|
};
|