From 13cc0b9346a960604cee0eb2f537f47ae2932ef1 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 13 Apr 2022 16:57:22 +0530 Subject: [PATCH] fix: FileUploader - New option: crop_image_aspect_ratio to force an aspect ratio during cropping - ImageCropper: Add aspect ratio buttons --- .../js/frappe/file_uploader/FileUploader.vue | 24 ++++-- .../js/frappe/file_uploader/ImageCropper.vue | 83 +++++++++++++++---- .../public/js/frappe/file_uploader/index.js | 20 +++-- .../public/js/frappe/form/controls/attach.js | 6 +- .../js/frappe/form/controls/attach_image.js | 1 - 5 files changed, 99 insertions(+), 35 deletions(-) diff --git a/frappe/public/js/frappe/file_uploader/FileUploader.vue b/frappe/public/js/frappe/file_uploader/FileUploader.vue index ff1afcdd3c..6c816c1115 100644 --- a/frappe/public/js/frappe/file_uploader/FileUploader.vue +++ b/frappe/public/js/frappe/file_uploader/FileUploader.vue @@ -36,7 +36,7 @@ ref="file_input" @change="on_file_input" :multiple="allow_multiple" - :accept="restrictions.allowed_file_types.join(', ')" + :accept="(restrictions.allowed_file_types || []).join(', ')" > - +
+
+ +
+
+
+ + +
@@ -15,22 +42,31 @@ import Cropper from "cropperjs"; export default { name: "ImageCropper", - props: ["file", "attach_doc_image"], + props: ["file", "fixed_aspect_ratio"], data() { + let aspect_ratio = + this.fixed_aspect_ratio != null ? this.fixed_aspect_ratio : NaN; return { src: null, cropper: null, - image: null + image: null, + aspect_ratio }; }, + watch: { + aspect_ratio(value) { + if (this.cropper) { + this.cropper.setAspectRatio(value); + } + } + }, mounted() { if (window.FileReader) { let fr = new FileReader(); fr.onload = () => (this.src = fr.result); fr.readAsDataURL(this.file.cropper_file); } - aspect_ratio = this.attach_doc_image ? 1 : NaN; - crop_box = this.file.crop_box_data; + let crop_box = this.file.crop_box_data; this.image = this.$refs.image; this.image.onload = () => { this.cropper = new Cropper(this.image, { @@ -38,13 +74,31 @@ export default { scalable: false, viewMode: 1, data: crop_box, - aspectRatio: aspect_ratio + aspectRatio: this.aspect_ratio }); + window.cropper = this.cropper; }; }, computed: { - crop_button_text() { - return this.attach_doc_image ? "Upload" : "Crop"; + aspect_ratio_buttons() { + return [ + { + label: __("1:1"), + value: 1 + }, + { + label: __("4:3"), + value: 4 / 3 + }, + { + label: __("16:9"), + value: 16 / 9 + }, + { + label: __("Free"), + value: NaN + } + ]; } }, methods: { @@ -58,9 +112,6 @@ export default { }); this.file.file_obj = cropped_file_obj; this.$emit("toggle_image_cropper"); - if(this.attach_doc_image) { - this.$emit("upload_after_crop"); - } }, file_type); } } @@ -75,6 +126,8 @@ img { .image-cropper-actions { display: flex; - justify-content: flex-end; + align-items: center; + justify-content: space-between; + margin-top: var(--margin-md); } diff --git a/frappe/public/js/frappe/file_uploader/index.js b/frappe/public/js/frappe/file_uploader/index.js index ec90b19a1a..ab074c938d 100644 --- a/frappe/public/js/frappe/file_uploader/index.js +++ b/frappe/public/js/frappe/file_uploader/index.js @@ -10,11 +10,12 @@ export default class FileUploader { fieldname, files, folder, - restrictions, + restrictions = {}, upload_notes, allow_multiple, as_dataurl, disable_file_browser, + dialog_title, attach_doc_image, frm } = {}) { @@ -22,15 +23,11 @@ export default class FileUploader { frm && frm.attachments.max_reached(true); if (!wrapper) { - this.make_dialog(); + this.make_dialog(dialog_title); } else { this.wrapper = wrapper.get ? wrapper.get(0) : wrapper; } - if (attach_doc_image) { - restrictions.allowed_file_types = ['image/jpeg', 'image/png']; - } - this.$fileuploader = new Vue({ el: this.wrapper, render: h => h(FileUploaderComponent, { @@ -54,6 +51,10 @@ export default class FileUploader { this.uploader = this.$fileuploader.$children[0]; + if (!this.dialog) { + this.uploader.wrapper_ready = true; + } + this.uploader.$watch('files', (files) => { let all_private = files.every(file => file.private); if (this.dialog) { @@ -94,14 +95,17 @@ export default class FileUploader { return this.uploader.upload_files(); } - make_dialog() { + make_dialog(title) { this.dialog = new frappe.ui.Dialog({ - title: __('Upload'), + title: title || __('Upload'), primary_action_label: __('Upload'), primary_action: () => this.upload_files(), secondary_action_label: __('Set all private'), secondary_action: () => { this.uploader.toggle_all_private(); + }, + on_page_show: () => { + this.uploader.wrapper_ready = true; } }); diff --git a/frappe/public/js/frappe/form/controls/attach.js b/frappe/public/js/frappe/form/controls/attach.js index a91058a208..71ce2e8854 100644 --- a/frappe/public/js/frappe/form/controls/attach.js +++ b/frappe/public/js/frappe/form/controls/attach.js @@ -61,7 +61,8 @@ frappe.ui.form.ControlAttach = class ControlAttach extends frappe.ui.form.Contro } on_attach_doc_image() { this.set_upload_options(); - this.upload_options["attach_doc_image"] = true; + this.upload_options.restrictions.allowed_file_types = ['image/*']; + this.upload_options.restrictions.crop_image_aspect_ratio = 1; this.file_uploader = new frappe.ui.FileUploader(this.upload_options); } set_upload_options() { @@ -70,7 +71,8 @@ frappe.ui.form.ControlAttach = class ControlAttach extends frappe.ui.form.Contro on_success: file => { this.on_upload_complete(file); this.toggle_reload_button(); - } + }, + restrictions: {} }; if (this.frm) { diff --git a/frappe/public/js/frappe/form/controls/attach_image.js b/frappe/public/js/frappe/form/controls/attach_image.js index 7c24ec9551..0bae2e6241 100644 --- a/frappe/public/js/frappe/form/controls/attach_image.js +++ b/frappe/public/js/frappe/form/controls/attach_image.js @@ -19,7 +19,6 @@ frappe.ui.form.ControlAttachImage = class ControlAttachImage extends frappe.ui.f } set_upload_options() { super.set_upload_options(); - this.upload_options.restrictions = {}; this.upload_options.restrictions.allowed_file_types = ['image/*']; } };