diff --git a/requirements/base.txt b/requirements/base.txt
index 7774738..03dd5b1 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -72,3 +72,4 @@ redis==2.10.5
trans==2.1.0
python-decouple==3.0
flake8==3.2.1
+numpy==1.13.0
diff --git a/src/customer/urls.py b/src/customer/urls.py
index 12b922f..b650399 100644
--- a/src/customer/urls.py
+++ b/src/customer/urls.py
@@ -82,4 +82,5 @@ urlpatterns = \
name='customer_clients_delete_ajax'),
url(r'^tmp_upload/ajax/$', profile.tmp_upload, name='upload_tmp_file'),
+ url(r'^upload-image/ajax/$', profile.upload_image, name='upload-image'),
)
diff --git a/src/customer/views/profile.py b/src/customer/views/profile.py
index 8880eb3..2f02946 100644
--- a/src/customer/views/profile.py
+++ b/src/customer/views/profile.py
@@ -1,11 +1,20 @@
# -*- coding: utf-8 -*-
import os
import json
+
+import shutil
import tempfile
+
+from PIL import Image
+import numpy as np
+
+from base64 import b64decode
from email.header import Header
+from django.core.files.storage import FileSystemStorage
from django.shortcuts import render, redirect
from django.core.files import File
+from django.core.files.base import ContentFile
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth.decorators import login_required
from django.template.loader import render_to_string
@@ -82,11 +91,14 @@ def profile_view(request):
@login_required
@csrf_protect
def profile_edit(request):
- """Редактировать профиль пользователя."""
+ """
+ Редактировать профиль пользователя.
+ """
raise_if_no_profile(request)
template_name = 'customer/profile/edit.html'
success_url = 'customer_profile_view'
+ tmp_dir = ''
if request.method == 'POST' and '_cancel' in request.POST:
return redirect(success_url)
@@ -105,20 +117,21 @@ def profile_edit(request):
item = form.save(commit=False)
for img_url in ('tmb_logo', 'tmb_boss_sign', 'tmb_glavbuh_sign', 'tmb_stamp'):
+
if form.cleaned_data[img_url]:
- # TODO ?
- chg_file = open(settings.MEDIA_ROOT + '/cache/imgs/' +
- form.cleaned_data[img_url], mode='rb+')
+ path = f'{settings.MEDIA_ROOT}/cache/images/{form.cleaned_data[img_url]}'
+ tmp_dir = form.cleaned_data[img_url].split('/')[0]
+ chg_file = open(path, mode='rb+')
item_attr = img_url[4:]
getattr(item, item_attr).\
save('%s.%s' % (item_attr, form.cleaned_data[img_url].split('.')[-1]),
File(chg_file))
chg_file.close()
- #
- elif form.cleaned_data:
- pass
+
item.save()
+ if tmp_dir:
+ shutil.rmtree(f'{settings.MEDIA_ROOT}/cache/images/{tmp_dir}')
return redirect(success_url)
else:
form = form_class(instance=profile)
@@ -161,6 +174,55 @@ def tmp_upload(request):
return HttpResponse(json.dumps(data), content_type='application/json')
+def save_file(path, file):
+ fs = FileSystemStorage()
+ file_path = fs.save(path, file)
+ return file_path
+
+
+def clean_background(file):
+
+ threshold = 100
+ dist = 5
+ img = Image.open(file).convert('RGBA')
+ # np.asarray(img) is read only. Wrap it in np.array to make it modifiable.
+ arr = np.array(np.asarray(img))
+ r, g, b, a = np.rollaxis(arr, axis=-1)
+ mask = ((r > threshold)
+ & (g > threshold)
+ & (b > threshold)
+ & (np.abs(r - g) < dist)
+ & (np.abs(r - b) < dist)
+ & (np.abs(g - b) < dist)
+ )
+ arr[mask, 3] = 0
+ img = Image.fromarray(arr, mode='RGBA')
+ img.save(file)
+ return file
+
+
+def upload_image(request):
+
+ name = request.POST.get('name')
+ if not os.path.exists(settings.MEDIA_ROOT + '/cache/images/'):
+ os.makedirs(settings.MEDIA_ROOT + '/cache/images/')
+ tmp_dir = tempfile.mkdtemp('img_tmp', settings.MEDIA_ROOT + '/cache/images/')
+ b64_text = request.POST.get('image')
+ format_file, img_str = b64_text.split(';base64,')
+ ext = format_file.split('/')[-1]
+ file_name = f'{name}.{ext}'
+ full_path = f'{tmp_dir}/{file_name}'
+ file = ContentFile(b64decode(img_str), name=file_name)
+ file = save_file(full_path, file)
+ if name != 'logo':
+ file = clean_background(file)
+ url = os.path.join(settings.MEDIA_URL, os.path.relpath(file, settings.MEDIA_ROOT))
+ short_url = os.path.basename(tmp_dir) + '/' + file_name
+ data = {'msg': 'success', 'url': url, 'short_url': short_url}
+
+ return HttpResponse(json.dumps(data), content_type='application/json')
+
+
@login_required
def _profile_get_pdf(request, profile=None, account=None, filters=None):
"""
diff --git a/src/dokumentor/static/js/profile/asset.js b/src/dokumentor/static/js/profile/asset.js
index 6d3f80f..d4dc89d 100644
--- a/src/dokumentor/static/js/profile/asset.js
+++ b/src/dokumentor/static/js/profile/asset.js
@@ -36,19 +36,50 @@ $(document).ready(function () {
}
}
- $uploadCrop = $('#imageCropper').croppie({
+ function getCropForm(field) {
+ var result;
+ if (field === 'stamp') {
+ result = 'circle'
+ } else {
+ result = 'square'
+ }
+ return result
+ }
+
+ function getCropHeight(field) {
+ var result;
+ if (field === 'stamp' || field === 'logo') {
+ result = 200
+ } else {
+ result = 76
+ }
+ return result
+ }
+
+ function initCropper(width, height, type) {
+ $uploadCrop = $('#imageCropper').croppie({
enableExif: true,
enforceBoundary: false,
viewport: {
- width: 200,
- height: 200,
- type: 'circle'
+ width: width,
+ height: height,
+ type: type
},
boundary: {
width: 300,
height: 300
}
- });
+ });
+ }
+
+ function uploadImageOnServer(data) {
+ // $('#' + imagePreview + ' img').attr('src', imgBase);
+ $('#' + imagePreview + ' img').attr('src', data['url']);
+ $('#id_tmb_' + imagePreview).val(data['short_url']);
+ $('#' + imagePreview + ' .del_image').show();
+ // console.log('id_tmb_' + imagePreview);
+ console.log(data)
+ }
// select file
$('.img_load img').on('click', function() {
@@ -62,7 +93,10 @@ $(document).ready(function () {
});
// set file in input hidden filed
- $('.img_load input[type=file]').on('change', function () {readFile(this)});
+ $('.img_load input[type=file]').on('change', function () {
+ initCropper(200,getCropHeight(imagePreview), getCropForm(imagePreview));
+ console.log($uploadCrop);
+ readFile(this)});
$('#containerUpload').on("ShowModal", function( ) {
$('#containerUpload').visible();
@@ -80,15 +114,32 @@ $(document).ready(function () {
size: 'viewport'
}).then(function (resp) {
// console.log(resp);
- $('#' + imagePreview + ' img').attr('src', resp);
+
+ var formData = new FormData();
+ formData.append('image', resp);
+ formData.append('name', imagePreview);
+
+ $.ajax({
+ type: 'POST',
+ url: '/my/upload-image/ajax/',
+ success: uploadImageOnServer,
+ data: formData,
+ cache: false,
+ contentType: false,
+ processData: false
+ }).done(function(json) {
+ console.log(json);
+ });
+
$('#containerUpload').trigger("CloseModal");
- $('#' + imagePreview + ' .del_image').show();
+
})
});
$('#containerUpload').on("CloseModal", function( ) {
$('#containerUpload').invisible();
$('#' + imageInputField).val('');
+ $('#imageCropper').croppie('destroy');
});
var closeButtons=document.getElementsByClassName("modal-upload__cleaner-btn");
diff --git a/src/dokumentor/templates/customer/profile/edit.html b/src/dokumentor/templates/customer/profile/edit.html
index cffe51a..a0d1065 100644
--- a/src/dokumentor/templates/customer/profile/edit.html
+++ b/src/dokumentor/templates/customer/profile/edit.html
@@ -509,93 +509,21 @@
};
+
+
+
+
+
+
+
+
- {% comment %}
-
-{% endcomment %}
-
-
-
-
-
-
-
-
-
-
- {% include 'hbs/bank-tpl.html' %}
+ {% include 'hbs/bank-tpl.html' %}
{% endblock js %}