mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FIX: form template upload type validation (#24148)
When submitting files through the form template upload field, we were having an issue where, although a validation error message was being presented to the user, the upload was still coming through, because `PickFilesButton`'s validation happens **after** the Uppy mixin finished the upload and hit `uploadDone`. This PR adds a new overridable method to the Uppy mixin and overrides it with the custom validation, which now happens before the file is sent. Additionally, we're now also using `uploadingOrProcessing` as the source of truth to show the upload/uploading label, which seems more reliable.
This commit is contained in:
parent
2b2f6b1c25
commit
2201f8f7dc
@ -12,38 +12,51 @@ export default class FormTemplateFieldUpload extends Component.extend(
|
|||||||
UppyUploadMixin
|
UppyUploadMixin
|
||||||
) {
|
) {
|
||||||
@tracked uploadValue;
|
@tracked uploadValue;
|
||||||
@tracked uploadComplete = false;
|
|
||||||
@tracked uploadedFiles = [];
|
@tracked uploadedFiles = [];
|
||||||
@tracked disabled = this.uploading;
|
@tracked disabled = this.uploadingOrProcessing;
|
||||||
@tracked fileUploadElementId = `${dasherize(this.id)}-uploader`;
|
@tracked fileUploadElementId = `${dasherize(this.id)}-uploader`;
|
||||||
@tracked fileInputSelector = `#${this.fileUploadElementId}`;
|
@tracked fileInputSelector = `#${this.fileUploadElementId}`;
|
||||||
|
|
||||||
type = "composer";
|
type = "composer";
|
||||||
|
|
||||||
@computed("uploading", "uploadValue")
|
@computed("uploadingOrProcessing")
|
||||||
get uploadStatusLabel() {
|
get uploadStatusLabel() {
|
||||||
if (!this.uploading && !this.uploadValue) {
|
return this.uploadingOrProcessing
|
||||||
return "form_templates.upload_field.upload";
|
? "form_templates.upload_field.uploading"
|
||||||
}
|
: "form_templates.upload_field.upload";
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.uploading && this.uploadValue) {
|
/**
|
||||||
this.uploadComplete = true;
|
* The validation from PickFilesButton._filesPicked, where acceptedFormatsOverride
|
||||||
return "form_templates.upload_field.upload";
|
* is validated and displays a message, happens after the upload is complete.
|
||||||
}
|
*
|
||||||
|
* Overriding this method allows us to validate the file before the upload
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isUploadedFileAllowed(file) {
|
||||||
|
// same logic from PickFilesButton._hasAcceptedExtensionOrType
|
||||||
|
const fileTypes = this.attributes.file_types;
|
||||||
|
const extension = file.name.split(".").pop();
|
||||||
|
|
||||||
return "form_templates.upload_field.uploading";
|
return (
|
||||||
|
!fileTypes ||
|
||||||
|
fileTypes.includes(`.${extension}`) ||
|
||||||
|
fileTypes.includes(file.type)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadDone(upload) {
|
uploadDone(upload) {
|
||||||
// If re-uploading, clear the existing file if multiple aren't allowed
|
// If re-uploading, clear the existing file if multiple aren't allowed
|
||||||
if (!this.attributes.allow_multiple && this.uploadComplete) {
|
if (!this.attributes.allow_multiple && this.uploadValue) {
|
||||||
this.uploadedFiles = [];
|
this.uploadedFiles = [];
|
||||||
this.uploadValue = "";
|
this.uploadValue = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadMarkdown = this.buildMarkdown(upload);
|
|
||||||
this.uploadedFiles.pushObject(upload);
|
this.uploadedFiles.pushObject(upload);
|
||||||
|
|
||||||
|
const uploadMarkdown = this.buildMarkdown(upload);
|
||||||
if (this.uploadValue && this.allowMultipleFiles) {
|
if (this.uploadValue && this.allowMultipleFiles) {
|
||||||
// multiple file upload
|
// multiple file upload
|
||||||
this.uploadValue = `${this.uploadValue}\n${uploadMarkdown}`;
|
this.uploadValue = `${this.uploadValue}\n${uploadMarkdown}`;
|
||||||
|
@ -47,6 +47,17 @@ export default Mixin.create(UppyS3Multipart, ExtendableUploader, {
|
|||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridable for custom file validations, executed before uploading.
|
||||||
|
*
|
||||||
|
* @param {object} file
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isUploadedFileAllowed() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
uploadingOrProcessing: or("uploading", "processing"),
|
uploadingOrProcessing: or("uploading", "processing"),
|
||||||
|
|
||||||
@on("willDestroyElement")
|
@on("willDestroyElement")
|
||||||
@ -112,7 +123,9 @@ export default Mixin.create(UppyS3Multipart, ExtendableUploader, {
|
|||||||
},
|
},
|
||||||
this.validateUploadedFilesOptions()
|
this.validateUploadedFilesOptions()
|
||||||
);
|
);
|
||||||
const isValid = validateUploadedFile(currentFile, validationOpts);
|
const isValid =
|
||||||
|
validateUploadedFile(currentFile, validationOpts) &&
|
||||||
|
this.isUploadedFileAllowed(currentFile);
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
uploadProgress: 0,
|
uploadProgress: 0,
|
||||||
uploading: isValid && this.autoStartUploads,
|
uploading: isValid && this.autoStartUploads,
|
||||||
|
@ -370,6 +370,7 @@ describe "Composer Form Templates", type: :system do
|
|||||||
expect(find("#dialog-holder .dialog-body p", visible: :all)).to have_content(
|
expect(find("#dialog-holder .dialog-body p", visible: :all)).to have_content(
|
||||||
I18n.t("js.pick_files_button.unsupported_file_picked", { types: ".jpg, .png" }),
|
I18n.t("js.pick_files_button.unsupported_file_picked", { types: ".jpg, .png" }),
|
||||||
)
|
)
|
||||||
|
expect(page).to have_no_css(".form-template-field__uploaded-files")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a post with multiple uploads" do
|
it "creates a post with multiple uploads" do
|
||||||
@ -401,6 +402,22 @@ describe "Composer Form Templates", type: :system do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "overrides uploaded file if allow_multiple false" do
|
||||||
|
topic_title = "Peter Parker's Medication"
|
||||||
|
|
||||||
|
category_page.visit(category_with_upload_template)
|
||||||
|
category_page.new_topic_button.click
|
||||||
|
attach_file "prescription-uploader",
|
||||||
|
"#{Rails.root}/spec/fixtures/images/logo.png",
|
||||||
|
make_visible: true
|
||||||
|
composer.fill_title(topic_title)
|
||||||
|
attach_file "prescription-uploader",
|
||||||
|
"#{Rails.root}/spec/fixtures/images/fake.jpg",
|
||||||
|
make_visible: true
|
||||||
|
|
||||||
|
expect(find(".form-template-field__uploaded-files")).to have_css("li", count: 1)
|
||||||
|
end
|
||||||
|
|
||||||
it "shows labels and descriptions when a form template is assigned to the category" do
|
it "shows labels and descriptions when a form template is assigned to the category" do
|
||||||
category_page.visit(category_with_template_6)
|
category_page.visit(category_with_template_6)
|
||||||
category_page.new_topic_button.click
|
category_page.new_topic_button.click
|
||||||
|
Loading…
Reference in New Issue
Block a user