feature media handler for stamp and sign

prod
Dmitriy Shesterkin 9 years ago
parent 2c337b5c1c
commit 99b28ce2d9
  1. 1
      requirements/base.txt
  2. 1
      src/customer/urls.py
  3. 76
      src/customer/views/profile.py
  4. 67
      src/dokumentor/static/js/profile/asset.js
  5. 102
      src/dokumentor/templates/customer/profile/edit.html

@ -72,3 +72,4 @@ redis==2.10.5
trans==2.1.0 trans==2.1.0
python-decouple==3.0 python-decouple==3.0
flake8==3.2.1 flake8==3.2.1
numpy==1.13.0

@ -82,4 +82,5 @@ urlpatterns = \
name='customer_clients_delete_ajax'), name='customer_clients_delete_ajax'),
url(r'^tmp_upload/ajax/$', profile.tmp_upload, name='upload_tmp_file'), url(r'^tmp_upload/ajax/$', profile.tmp_upload, name='upload_tmp_file'),
url(r'^upload-image/ajax/$', profile.upload_image, name='upload-image'),
) )

@ -1,11 +1,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import json import json
import shutil
import tempfile import tempfile
from PIL import Image
import numpy as np
from base64 import b64decode
from email.header import Header from email.header import Header
from django.core.files.storage import FileSystemStorage
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.core.files import File from django.core.files import File
from django.core.files.base import ContentFile
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.template.loader import render_to_string from django.template.loader import render_to_string
@ -82,11 +91,14 @@ def profile_view(request):
@login_required @login_required
@csrf_protect @csrf_protect
def profile_edit(request): def profile_edit(request):
"""Редактировать профиль пользователя.""" """
Редактировать профиль пользователя.
"""
raise_if_no_profile(request) raise_if_no_profile(request)
template_name = 'customer/profile/edit.html' template_name = 'customer/profile/edit.html'
success_url = 'customer_profile_view' success_url = 'customer_profile_view'
tmp_dir = ''
if request.method == 'POST' and '_cancel' in request.POST: if request.method == 'POST' and '_cancel' in request.POST:
return redirect(success_url) return redirect(success_url)
@ -105,20 +117,21 @@ def profile_edit(request):
item = form.save(commit=False) item = form.save(commit=False)
for img_url in ('tmb_logo', 'tmb_boss_sign', 'tmb_glavbuh_sign', 'tmb_stamp'): for img_url in ('tmb_logo', 'tmb_boss_sign', 'tmb_glavbuh_sign', 'tmb_stamp'):
if form.cleaned_data[img_url]: if form.cleaned_data[img_url]:
# TODO ? path = f'{settings.MEDIA_ROOT}/cache/images/{form.cleaned_data[img_url]}'
chg_file = open(settings.MEDIA_ROOT + '/cache/imgs/' + tmp_dir = form.cleaned_data[img_url].split('/')[0]
form.cleaned_data[img_url], mode='rb+') chg_file = open(path, mode='rb+')
item_attr = img_url[4:] item_attr = img_url[4:]
getattr(item, item_attr).\ getattr(item, item_attr).\
save('%s.%s' % (item_attr, form.cleaned_data[img_url].split('.')[-1]), save('%s.%s' % (item_attr, form.cleaned_data[img_url].split('.')[-1]),
File(chg_file)) File(chg_file))
chg_file.close() chg_file.close()
#
elif form.cleaned_data:
pass
item.save() item.save()
if tmp_dir:
shutil.rmtree(f'{settings.MEDIA_ROOT}/cache/images/{tmp_dir}')
return redirect(success_url) return redirect(success_url)
else: else:
form = form_class(instance=profile) form = form_class(instance=profile)
@ -161,6 +174,55 @@ def tmp_upload(request):
return HttpResponse(json.dumps(data), content_type='application/json') 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 @login_required
def _profile_get_pdf(request, profile=None, account=None, filters=None): def _profile_get_pdf(request, profile=None, account=None, filters=None):
""" """

@ -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, enableExif: true,
enforceBoundary: false, enforceBoundary: false,
viewport: { viewport: {
width: 200, width: width,
height: 200, height: height,
type: 'circle' type: type
}, },
boundary: { boundary: {
width: 300, width: 300,
height: 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 // select file
$('.img_load img').on('click', function() { $('.img_load img').on('click', function() {
@ -62,7 +93,10 @@ $(document).ready(function () {
}); });
// set file in input hidden filed // 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').on("ShowModal", function( ) {
$('#containerUpload').visible(); $('#containerUpload').visible();
@ -80,15 +114,32 @@ $(document).ready(function () {
size: 'viewport' size: 'viewport'
}).then(function (resp) { }).then(function (resp) {
// console.log(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"); $('#containerUpload').trigger("CloseModal");
$('#' + imagePreview + ' .del_image').show();
}) })
}); });
$('#containerUpload').on("CloseModal", function( ) { $('#containerUpload').on("CloseModal", function( ) {
$('#containerUpload').invisible(); $('#containerUpload').invisible();
$('#' + imageInputField).val(''); $('#' + imageInputField).val('');
$('#imageCropper').croppie('destroy');
}); });
var closeButtons=document.getElementsByClassName("modal-upload__cleaner-btn"); var closeButtons=document.getElementsByClassName("modal-upload__cleaner-btn");

@ -509,93 +509,21 @@
}; };
</script> </script>
<script src="{% static 'js/customer/profile.edit.js' %}"></script>
<script src="{% static 'vendor/suggestions.jquery/dist/js/jquery.suggestions.min.js' %}"></script>
<script src="{% static 'vendor/Croppie/croppie.min.js' %}"></script>
<script>
$(document).ready(function() {
var False = false,
True = true;
window.isOrg = {{ profile.is_org }};
});
</script>
<script src="{% static 'js/profile/search-main-external-api.js' %}"></script>
<script src="{% static 'js/profile/search-bank-external-api.js' %}"></script>
<script src="{% static 'js/profile/asset.js' %}"></script>
{% comment %} {% include 'hbs/bank-tpl.html' %}
<script type="text/javascript">
var BANK_ACCOUNT = {
'list_url': "{% url 'customer_bank_accounts_list_ajax' %}",
'edit_id_prefix': "account_edit_link_",
'delete_id_prefix': "account_delete_link_",
'bank_id_prefix': "account_bank_name_"
};
$(function(){
$('.img_load img').on('click', function(e) {
var this_id = $(this).closest('.img_load').attr('id');
var tmb_id = 'id_tmb_' + this_id.substring(3);
$('#' + tmb_id).val('');
$('#id_' + this_id).click();
});
$('.img_load .del_image').on('click', function(e) {
e.preventDefault();
var this_id = $(this).closest('.img_load').attr('id');
var tmb_id = 'id_tmb_' + this_id.substring(3);
var dlg_msg = $('#dialog-message');
dlg_msg.dialog({
title: 'Удалить изображение?',
buttons:{'Да': function(){
$('#' + tmb_id).val('');
$('#' + this_id + ' img').attr('src', '{{ STATIC_URL }}/img/upload-' + this_id + '.png');
$('#' + this_id + '-clear_id').attr('checked', true);
$('#' + this_id + ' .del_image').hide();
dlg_msg.dialog('close');
},
'Нет': function(){
dlg_msg.dialog('close');
}
}
}).html('Нажмите "Да", чтобы удалить изображение');
dlg_msg.dialog('open');
});
var getPic = function(data){
var elm_id = '#' + data['elm_id'].substring(3);
var tmb_id = '#id_tmb_' + data['elm_id'].substring(3);
$(elm_id + ' img').attr('src', data['pic']);
$(tmb_id).val(data['full_pic']);
$(elm_id + ' .del_image').show();
};
$('.img_load input[type=file]').on('change', function(e){
e.preventDefault();
var this_id = $(this).attr('id').substring(3);
console.log($('#' + this_id + ' img'));
$('#' + this_id + ' img').attr('src', "{% static 'img/spinner.gif' %}");
var formData = new FormData();
formData.append($(this).val(), $(this)[0].files[0]);
formData.append('elm_id', $(this).attr('id'));
$.ajax({
type: 'POST',
url: '/my/tmp_upload/ajax/',
success: getPic,
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function() {
});
});
})
</script>
{% endcomment %}
<script src="{% static 'js/customer/profile.edit.js' %}"></script>
<script src="{% static 'vendor/suggestions.jquery/dist/js/jquery.suggestions.min.js' %}"></script>
<script src="{% static 'vendor/Croppie/croppie.min.js' %}"></script>
<script>
$(document).ready(function() {
var False = false,
True = true;
window.isOrg = {{ profile.is_org }};
});
</script>
<script src="{% static 'js/profile/search-main-external-api.js' %}"></script>
<script src="{% static 'js/profile/search-bank-external-api.js' %}"></script>
<script src="{% static 'js/profile/asset.js' %}"></script>
{% include 'hbs/bank-tpl.html' %}
{% endblock js %} {% endblock js %}

Loading…
Cancel
Save