mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 07:49:57 +01:00 
			
		
		
		
	add support for cropping image. WIP.
This commit is contained in:
		| @@ -16,6 +16,7 @@ from django.core.exceptions import ValidationError | ||||
| from django_tables2.views import SingleTableView | ||||
| from rest_framework.authtoken.models import Token | ||||
| from dal import autocomplete | ||||
| from PIL import Image | ||||
|  | ||||
| from note.models import Alias, NoteUser | ||||
| from note.models.transactions import Transaction | ||||
| @@ -229,8 +230,16 @@ class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView): | ||||
|             return self.form_invalid(form) | ||||
|  | ||||
|     def form_valid(self,form): | ||||
|         print(form) | ||||
|         self.object.note.display_image = form.cleaned_data.get("image","pic/default.png") | ||||
|         image_file_field = form.cleaned_data['image'] | ||||
|         x = form.cleaned_data['x'] | ||||
|         y = form.cleaned_data['y'] | ||||
|         w = form.cleaned_data['width'] | ||||
|         h = form.cleaned_data['height'] | ||||
|         with Image.open(image_file_field.name) as image: | ||||
|             image = image.crop((x, y, w+x, h+y)) | ||||
|             image.thumbnail((256, 256), Image.ANTIALIAS) | ||||
|             image.save(image_file_field.name,format=image.format) | ||||
|         self.object.note.display_image = image_file_field | ||||
|         self.object.note.save() | ||||
|         return super().form_valid(form) | ||||
|  | ||||
|   | ||||
| @@ -3,8 +3,11 @@ | ||||
|  | ||||
| from dal import autocomplete | ||||
| from django import forms | ||||
| from django.conf import settings | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
|  | ||||
| import os | ||||
|  | ||||
| from crispy_forms.helper import FormHelper | ||||
| from crispy_forms.bootstrap import Div | ||||
| from crispy_forms.layout import Layout, HTML | ||||
| @@ -27,8 +30,12 @@ class ImageForm(forms.Form): | ||||
|     image = forms.ImageField(required = False, | ||||
|                              label=_('select an image'), | ||||
|                              help_text=_('Maximal size: 2MB')) | ||||
|     x = forms.FloatField(widget=forms.HiddenInput()) | ||||
|     y = forms.FloatField(widget=forms.HiddenInput()) | ||||
|     width = forms.FloatField(widget=forms.HiddenInput()) | ||||
|     height = forms.FloatField(widget=forms.HiddenInput()) | ||||
|  | ||||
|  | ||||
|     | ||||
| class TransactionTemplateForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = TransactionTemplate | ||||
|   | ||||
| @@ -191,3 +191,7 @@ ALIAS_VALIDATOR_REGEX = r'' | ||||
|  | ||||
| MEDIA_ROOT=os.path.join(BASE_DIR,"media") | ||||
| MEDIA_URL='/media/' | ||||
|  | ||||
| # Profile Picture Settings | ||||
| PIC_WIDTH = 200 | ||||
| PIC_RATIO = 1 | ||||
|   | ||||
| @@ -26,3 +26,4 @@ urlpatterns = [ | ||||
| ] | ||||
|  | ||||
| urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT) | ||||
| urlpatterns += static(settings.STATIC_URL,document_root=settings.STATIC_ROOT) | ||||
|   | ||||
| @@ -2,62 +2,94 @@ | ||||
| {% load i18n static pretty_money django_tables2 crispy_forms_tags %} | ||||
|  | ||||
| {% block profile_content %} | ||||
| <div class="row"> | ||||
| <div class="col-sm-4 text-center"> | ||||
|     <img class="img-thumbnail" alt="" src="{{user_object.note.display_image.url }}"/> | ||||
|     <p class=""> {% trans "current image" %} </p> | ||||
| </div> | ||||
| <div class="col-sm-4 justify-content-center"> | ||||
|     <form class=" text-center form my-2" action="" enctype="multipart/form-data" method="post"> | ||||
|         {% csrf_token %} | ||||
|         {{ form |crispy }} | ||||
|         <button class="btn btn-primary mx-2" type="submit"> | ||||
|             {% trans "Change image" %} | ||||
|         </button> | ||||
|     </form> | ||||
| </div> | ||||
| <div class="col-sm-4"> | ||||
|     <div id="image-holder"></div> | ||||
| </div> | ||||
| <form method="post" enctype="multipart/form-data" id="formUpload"> | ||||
|   {% csrf_token %} | ||||
|   {{ form |crispy }} | ||||
| </form> | ||||
| <!-- MODAL TO CROP THE IMAGE --> | ||||
| <div class="modal fade" id="modalCrop"> | ||||
|   <div class="modal-dialog"> | ||||
|     <div class="modal-content"> | ||||
|       <div class="modal-body"> | ||||
|         <img src="" id="modal-image" style="max-width: 100%;"> | ||||
|       </div> | ||||
|       <div class="modal-footer"> | ||||
|         <div class="btn-group pull-left" role="group"> | ||||
|           <button type="button" class="btn btn-default" id="js-zoom-in"> | ||||
|             <span class="glyphicon glyphicon-zoom-in"></span> | ||||
|           </button> | ||||
|           <button type="button" class="btn btn-default js-zoom-out"> | ||||
|             <span class="glyphicon glyphicon-zoom-out"></span> | ||||
|           </button> | ||||
|         </div> | ||||
|         <button type="button" class="btn btn-default" data-dismiss="modal">Nevermind</button> | ||||
|         <button type="button" class="btn btn-primary js-crop-and-upload">Crop and upload</button> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block extracss %} | ||||
|     <link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.css" rel="stylesheet"> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block extrajavascript%} | ||||
| <script> | ||||
| // https://codepedia.info/upload-image-using-jquery-ajax-asp-net-c-sharp/ | ||||
|  $("#id_image").on('change', function () { | ||||
|  | ||||
|      //Get count of selected files | ||||
|      var countFiles = $(this)[0].files.length; | ||||
|  | ||||
|      var imgPath = $(this)[0].value; | ||||
|      var extn = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase(); | ||||
|      var image_holder = $("#image-holder"); | ||||
|      image_holder.empty(); | ||||
|  | ||||
|      if (extn == "gif" || extn == "png" || extn == "jpg" || extn == "jpeg") { | ||||
|          if (typeof (FileReader) != "undefined") { | ||||
|  | ||||
|              //loop for each file selected for uploaded. | ||||
|              for (var i = 0; i < countFiles; i++) { | ||||
|     <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.js"></script> | ||||
|     <script src="https://cdn.jsdelivr.net/npm/jquery-cropper@1.0.1/dist/jquery-cropper.min.js"></script> | ||||
|     <script> | ||||
|      $(function () { | ||||
|  | ||||
|          /* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */ | ||||
|          $("#id_image").change(function (e) { | ||||
|              if (this.files && this.files[0]) { | ||||
|                  var reader = new FileReader(); | ||||
|                  reader.onload = function (e) { | ||||
|                      $("<img />", { | ||||
|                          "src": e.target.result, | ||||
|                          "class": "img-thumbnail" | ||||
|                      }).appendTo(image_holder); | ||||
|                      $("#modal-image").attr("src", e.target.result); | ||||
|                      $("#modalCrop").modal("show"); | ||||
|                  } | ||||
|  | ||||
|                  image_holder.show(); | ||||
|                  reader.readAsDataURL($(this)[0].files[i]); | ||||
|                  reader.readAsDataURL(this.files[0]); | ||||
|              } | ||||
|          }); | ||||
|  | ||||
|          } else { | ||||
|              alert("{% trans 'This browser does not support FileReader.' %}"); | ||||
|          } | ||||
|      } else { | ||||
|          alert("{% trans 'Please select only images' %}"); | ||||
|      } | ||||
|  }); | ||||
| </script> | ||||
|          /* SCRIPTS TO HANDLE THE CROPPER BOX */ | ||||
|          var $image = $("#modal-image"); | ||||
|          var cropBoxData; | ||||
|          var canvasData; | ||||
|          $("#modalCrop").on("shown.bs.modal", function () { | ||||
|              $image.cropper({ | ||||
|                  viewMode: 1, | ||||
|                  aspectRatio: 1/1, | ||||
|                  minCropBoxWidth: 200, | ||||
|                  minCropBoxHeight: 200, | ||||
|                  ready: function () { | ||||
|                      $image.cropper("setCanvasData", canvasData); | ||||
|                      $image.cropper("setCropBoxData", cropBoxData); | ||||
|                  } | ||||
|              }); | ||||
|          }).on("hidden.bs.modal", function () { | ||||
|              cropBoxData = $image.cropper("getCropBoxData"); | ||||
|              canvasData = $image.cropper("getCanvasData"); | ||||
|              $image.cropper("destroy"); | ||||
|          }); | ||||
|  | ||||
|          $(".js-zoom-in").click(function () { | ||||
|              $image.cropper("zoom", 0.1); | ||||
|          }); | ||||
|  | ||||
|          $(".js-zoom-out").click(function () { | ||||
|              $image.cropper("zoom", -0.1); | ||||
|          }); | ||||
|  | ||||
|          /* SCRIPT TO COLLECT THE DATA AND POST TO THE SERVER */ | ||||
|          $(".js-crop-and-upload").click(function () { | ||||
|              var cropData = $image.cropper("getData"); | ||||
|              $("#id_x").val(cropData["x"]); | ||||
|              $("#id_y").val(cropData["y"]); | ||||
|              $("#id_height").val(cropData["height"]); | ||||
|              $("#id_width").val(cropData["width"]); | ||||
|              $("#formUpload").submit(); | ||||
|          }); | ||||
|  | ||||
|      }); | ||||
|     </script> | ||||
| {% endblock %} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user