remotes/origin/PR-39
Mukhtar 10 years ago
commit 0e43a71f2b
  1. 53
      assets/index.js
  2. 11
      common/admin.py
  3. 9
      common/mixins.py
  4. 3
      common/models.py
  5. 129
      common/views.py
  6. 20
      templates/partials/base.html
  7. 15
      templates/partials/header.html
  8. 15
      users/forms.py
  9. 23
      users/templates/contractor_profile.html
  10. 39
      users/templates/user_financial_info_edit.html
  11. 58
      users/templates/user_profile_edit.html
  12. 28
      users/views.py

@ -416,6 +416,59 @@ function loadAllPhotos(portfIds) {
// Live image upload ---------------------------------------
var $liveImageUploadContainer = $('.-live-image-upload-container').first()
var $avatarImage = $liveImageUploadContainer.find('.-avatar-image').first()
var $liveImageUpload = $liveImageUploadContainer.find('.-live-image-upload').first()
var $liveImageId = $liveImageUploadContainer.find('.-live-image-id').first()
var $liveImageDelete = $liveImageUploadContainer.find('.-live-image-delete').first()
var stubImageUrl = $liveImageUploadContainer.data('stubImageUrl')
$liveImageUpload.fileupload({
dataType: 'json',
done: function($evt, data) {
var image = data.result.files[0]
$avatarImage.attr('src', image.thumbnailUrl)
$liveImageId.val(image.id)
$liveImageDelete.data('url', image.deleteUrl)
$liveImageDelete.css('display', 'block')
}
})
$liveImageDelete.on('click', function($evt) {
var $that = $(this)
$.post($that.data('url')).then(function(res) {
if (res.status == 'success') {
$avatarImage.attr('src', stubImageUrl)
$liveImageId.val('')
$that.css('display', 'none')
}
})
})
// Helpers --------------------------------------------- // Helpers ---------------------------------------------

@ -3,7 +3,15 @@ from django.contrib import admin
from mptt.admin import MPTTModelAdmin from mptt.admin import MPTTModelAdmin
import pydash as _; _.map = _.map_; _.filter = _.filter_ import pydash as _; _.map = _.map_; _.filter = _.filter_
from .models import Location, MainPage, Settings, PrintOrder, PrintDocuments, Tooltip from .models import (
LiveImageUpload,
Location,
MainPage,
PrintDocuments,
PrintOrder,
Settings,
Tooltip,
)
class LocationAdmin(MPTTModelAdmin): class LocationAdmin(MPTTModelAdmin):
@ -59,6 +67,7 @@ class TooltipAdmin(admin.ModelAdmin):
form = TooltipAdminForm form = TooltipAdminForm
admin.site.register(LiveImageUpload)
admin.site.register(Location, LocationAdmin) admin.site.register(Location, LocationAdmin)
admin.site.register(MainPage, MainPageAdmin) admin.site.register(MainPage, MainPageAdmin)
admin.site.register(PrintDocuments) admin.site.register(PrintDocuments)

@ -0,0 +1,9 @@
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View
class NoCsrfMixin(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)

@ -112,7 +112,8 @@ class LiveImageUpload(models.Model):
created_at = models.DateTimeField(default=timezone.now) created_at = models.DateTimeField(default=timezone.now)
class Meta: class Meta:
verbose_name = 'LiveImageUpload' verbose_name = 'Живая загрузка изображений'
verbose_name_plural = 'Живая загрузка изображений'
def __str__(self): def __str__(self):
return self.file.url return self.file.url

@ -1,12 +1,12 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail, EmailMultiAlternatives from django.core.mail import send_mail, EmailMultiAlternatives
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.http import JsonResponse from django.http import JsonResponse
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.template.loader import get_template, render_to_string from django.template.loader import get_template, render_to_string
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View, DetailView from django.views.generic import View, DetailView
from registration.backends.default.views import RegistrationView from registration.backends.default.views import RegistrationView
import json import json
@ -16,6 +16,7 @@ from .forms import PrintOrderForm, CustomRegistrationForm
from .models import PrintDocuments, PrintOrder, Settings, LiveImageUpload from .models import PrintDocuments, PrintOrder, Settings, LiveImageUpload
from archilance import util from archilance import util
from archilance.mixins import BaseMixin from archilance.mixins import BaseMixin
from common.mixins import NoCsrfMixin
from users.models import ContractorResume from users.models import ContractorResume
@ -81,100 +82,36 @@ class PrintDocumentCreate(BaseMixin, View):
class LiveImageUploadCreateView(View): class LiveImageUploadCreateView(NoCsrfMixin, LoginRequiredMixin, View):
@method_decorator(csrf_exempt) def post(self, request, *args, **kwargs):
def dispatch(self, request, *args, **kwargs): image = request.FILES.get('image')
return super().dispatch(request, *args, **kwargs)
if not image:
def post(self, request, *args, **kwargs): return JsonResponse({'files': [{'error': 'No image provided'}]})
# try: data = json.loads(request.body.decode('utf-8'))
# except: data = {} live_img = LiveImageUpload.objects.create(file=image)
#
# crop = data.get('crop') return JsonResponse({'files': [{
# image_id = data.get('imageId') 'id': live_img.pk,
# 'name': live_img.file.name,
# if crop and image_id: 'size': live_img.file.size,
# old_pic = util.get_or_none(models.TmpAdvertPicture, pk=image_id) 'url': live_img.file.url,
# 'thumbnailUrl': live_img.file.url,
# if old_pic: 'deleteUrl': reverse('common:live-image-upload-delete', kwargs={'pk': live_img.pk}),
# try: img = pil.Image.open(old_pic.file) 'deleteType': 'POST',
# except IOError: return http.JsonResponse({'files': [{'error': "Couldn't open an image"}]}) }]})
#
# format = img.format
# class LiveImageUploadDeleteView(NoCsrfMixin, LoginRequiredMixin, View):
# # exif = img._getexif() def post(self, request, *args, **kwargs):
# # live_img = util.get_or_none(LiveImageUpload, pk=kwargs.get('pk'))
# # if exif:
# # orientation_exif_tag = 274 if live_img:
# # rotated_img = img.rotate({3: 180, 6: 270, 8: 90}[exif[orientation_exif_tag]]) live_img.file.delete()
# live_img.delete()
# rotation = -crop.get('rotate') return JsonResponse({'status': 'success'})
# else:
# if rotation: return JsonResponse({'status': 'failure'})
# img = img.rotate(rotation, expand=True)
#
# x, y = crop.get('x'), crop.get('y')
# x2, y2 = x + crop.get('width'), y + crop.get('height')
#
# cropped_img = img.crop((x, y, x2, y2)) # Left, upper, right, lower
#
# with io.BytesIO() as f:
# cropped_img.save(f, format=format)
# pic = models.TmpAdvertPicture.objects.create()
# pic.file.save(old_pic.file.name, ContentFile(f.getvalue()))
# pic.save()
#
# old_pic.file.delete()
# old_pic.delete()
# else:
# return http.JsonResponse({'files': [{'error': 'No image found'}]})
# else:
# image = request.FILES.get('_images')
#
# if image:
# pic = models.TmpAdvertPicture.objects.create(file=image)
# else:
# return http.JsonResponse({'files': [{'error': 'No image provided'}]})
#------------------------------------------------
print('###########################################')
print('Uploading a file...')
print('###########################################')
image = request.FILES.get('image')
if image:
img = LiveImageUpload.objects.create(file=image)
else:
return JsonResponse({'files': [{'error': 'No image provided'}]})
return JsonResponse({'files': [{
'id': img.pk,
'name': img.file.name,
'size': img.file.size,
'url': img.file.url,
'thumbnailUrl': img.file.url,
'deleteUrl': reverse('common:live-image-upload-delete', kwargs={'pk': img.pk}),
'deleteType': 'POST',
}]})
class LiveImageUploadDeleteView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
img = util.get_or_none(LiveImageUpload, pk=kwargs.get('pk'))
if img:
img.file.delete()
img.delete()
return JsonResponse({'success': True})
else:
return JsonResponse({'success': False})
class CustomRegistrationView(RegistrationView): class CustomRegistrationView(RegistrationView):

@ -79,8 +79,6 @@
<script src='{% static "js/main.js" %}'></script> <!-- Файл верстальщика --> <script src='{% static "js/main.js" %}'></script> <!-- Файл верстальщика -->
<script src='{% static "index.js" %}'></script> <!-- Файл программистов --> <script src='{% static "index.js" %}'></script> <!-- Файл программистов -->
{% block js_block %}{% endblock %}
<script> <script>
var SocketHandlerMain = function (userId) { var SocketHandlerMain = function (userId) {
var domain = '{{ request.META.HTTP_HOST }}'; var domain = '{{ request.META.HTTP_HOST }}';
@ -110,14 +108,20 @@
$.jGrowl("Вам пришло новое сообщение!<br />" + outMessage, { life: 15000}); $.jGrowl("Вам пришло новое сообщение!<br />" + outMessage, { life: 15000});
}; };
this.add_message = function (messageData) {
sock.send(JSON.stringify(messageData));
};
} }
}; };
$(function () {
var userId = '{{ request.user.pk }}'; var userId = '{{ request.user.pk }}';
if (userId) {
var socketMain = new SocketHandlerMain(userId); if (userId) {
} var socketMain = new SocketHandlerMain(userId);
}); }
</script> </script>
{% block js_block %}{% endblock %}
</body> </body>
</html> </html>

@ -3,6 +3,12 @@
{% load user_tags %} {% load user_tags %}
{% load activeurl %} {% load activeurl %}
{% if request.user.is_contractor %}
{% url 'users:contractor-profile' pk=request.user.pk as profile_url %}
{% elif request.user.is_customer %}
{% url 'users:customer-profile-open-projects' pk=request.user.pk as profile_url %}
{% endif %}
<div class="wrTop {% if request.user.is_authenticated %} disTab {% endif %}"> <div class="wrTop {% if request.user.is_authenticated %} disTab {% endif %}">
<div class="container-fluid topMain"> <div class="container-fluid topMain">
<div class="row"> <div class="row">
@ -62,7 +68,7 @@
<div class="col-lg-2"> <div class="col-lg-2">
<div class="imgProfile"> <div class="imgProfile">
{% if request.user.is_contractor %} {% if request.user.is_contractor %}
<a href="{% url 'users:contractor-profile' pk=request.user.pk %}"> <a href="{{ profile_url }}">
{% if request.user.avatar %} {% if request.user.avatar %}
{% thumbnail request.user.avatar "75x75" crop="center" as im %} {% thumbnail request.user.avatar "75x75" crop="center" as im %}
<img src="{{ im.url }}" alt="profile-image"> <img src="{{ im.url }}" alt="profile-image">
@ -72,7 +78,7 @@
{% endif %} {% endif %}
</a> </a>
{% elif request.user.is_customer %} {% elif request.user.is_customer %}
<a href="{% url 'users:customer-profile-open-projects' pk=request.user.pk %}"> <a href="{{ profile_url }}">
{% if request.user.avatar %} {% if request.user.avatar %}
{% thumbnail request.user.avatar "75x75" crop="center" as im %} {% thumbnail request.user.avatar "75x75" crop="center" as im %}
<img src="{{ im.url }}" alt="profile-image"> <img src="{{ im.url }}" alt="profile-image">
@ -106,6 +112,11 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
<li class="icon_mm3">
<a href="{{ profile_url }}">
Профиль<span></span>
</a>
</li>
<li class="icon_mm3"> <li class="icon_mm3">
<a href="{% url 'chat:chat-user' %}">Сообщения<span></span></a> <a href="{% url 'chat:chat-user' %}">Сообщения<span></span></a>
</li> </li>

@ -3,7 +3,7 @@ import itertools
import pydash as _; _.map = _.map_; _.filter = _.filter_ import pydash as _; _.map = _.map_; _.filter = _.filter_
from .models import User, UserFinancialInfo, Team, ContractorResume, ContractorResumeFiles, GENDERS from .models import User, UserFinancialInfo, Team, ContractorResume, ContractorResumeFiles, GENDERS
from common.models import Location from common.models import Location, LiveImageUpload
from projects.models import Project, Realty, BuildingClassfication, ConstructionType from projects.models import Project, Realty, BuildingClassfication, ConstructionType
from specializations.models import Specialization from specializations.models import Specialization
@ -36,7 +36,6 @@ class ContractorResumeFilesForm(forms.ModelForm):
) )
class UserProfileEditForm(forms.ModelForm): class UserProfileEditForm(forms.ModelForm):
gender = forms.ChoiceField( gender = forms.ChoiceField(
choices=GENDERS, choices=GENDERS,
@ -44,11 +43,15 @@ class UserProfileEditForm(forms.ModelForm):
required=False, required=False,
) )
live_image = forms.ModelChoiceField(
queryset=LiveImageUpload.objects.all(),
required=False,
)
class Meta: class Meta:
model = User model = User
fields = ( fields = (
# 'avatar', #...........................
'contractor_specializations', 'contractor_specializations',
'cro', 'cro',
'date_of_birth', 'date_of_birth',
@ -73,11 +76,15 @@ class UserProfileEditForm(forms.ModelForm):
class UserProfileBasicInfoEditForm(forms.ModelForm): class UserProfileBasicInfoEditForm(forms.ModelForm):
live_image = forms.ModelChoiceField(
queryset=LiveImageUpload.objects.all(),
required=False,
)
class Meta: class Meta:
model = User model = User
fields = ( fields = (
'avatar',
'contractor_specializations', 'contractor_specializations',
'first_name', 'first_name',
'last_name', 'last_name',

@ -23,7 +23,7 @@
</div> </div>
<div class="menuUser disTab"> <div class="menuUser disTab">
<ul> <ul>
{% if contractor.pk == user.pk %} {% if contractor.pk == request.user.pk %}
<li class="icon_um1"> <li class="icon_um1">
<a href="{% url 'users:user-profile-edit' pk=contractor.pk %}"> <a href="{% url 'users:user-profile-edit' pk=contractor.pk %}">
редактировать профиль редактировать профиль
@ -766,13 +766,32 @@
// A wysiwyg editor ------------------------------------- // A wysiwyg editor ----------------------------------------------
$('textarea.-ckeditor').first().ckeditor() $('textarea.-ckeditor').first().ckeditor()
// Team invitation -----------------------------------------------
function inviteToTeam(msg) {
socketMain.add_message({
format_type: 'add_message_contact',
data: {
sender_id: {{ request.user.pk }},
recipent_id: {{ contractor.pk }},
chat_message: msg,
},
})
}
window.inviteToTeam = inviteToTeam
//----------------------------------------------------------------- //-----------------------------------------------------------------

@ -3,6 +3,19 @@
{% load thumbnail %} {% load thumbnail %}
{% block head_css %}
<style>
.-live-image-delete-parent {position: relative}
.-live-image-delete {
position: absolute;
top: 0;
right: 0;
background-color: white;
}
</style>
{% endblock %}
{% block content %} {% block content %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
@ -19,25 +32,34 @@
<div class="projectsBlock disTab"> <div class="projectsBlock disTab">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="col-lg-3 divCol3"> <div class="col-lg-3 divCol3 -live-image-upload-container" data-stub-image-url="{% static 'img/profile.jpg' %}">
<div class="avatar"> <div class="avatar">
<div class="avatarInset"> <div class="avatarInset -live-image-delete-parent">
{% if form.avatar.value %} <a href="#" onclick="return false" class="btn close -live-image-delete" style="display: none">&times;</a>
{% thumbnail form.avatar.value "235x224" crop="center" as im %}
<img src="{{ im.url }}" alt="profile-image"> {% if request.user.avatar %}
{% thumbnail request.user.avatar "235x224" crop="center" as avatar %}
<img src="{{ avatar.url }}" alt="profile-image" class="-avatar-image">
{% endthumbnail %} {% endthumbnail %}
{% else %} {% else %}
<img src="{% static 'img/profile.jpg' %}" alt="profile-image"> <img src="{% static 'img/profile.jpg' %}" alt="profile-image" class="-avatar-image">
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="menuUser upload-img disTab"> <div class="menuUser upload-img disTab">
<div class="upload2 up-l1"> <div class="upload2 up-l1">
<input type="file" name="{{ form.avatar.html_name }}"> <input type="file" name="image" data-url="{% url 'common:live-image-upload-create' %}" class="-live-image-upload">
<p>Загрузить фотографию</p> <p>Загрузить фотографию</p>
</div> </div>
</div> </div>
<div {% if not TESTING %}style="display: none"{% endif %}>
<input type="text" name="live_image" class="-live-image-id">
</div>
</div> </div>
<div class="col-lg-9 divCol9"> <div class="col-lg-9 divCol9">
<div class="col-lg-4"> <div class="col-lg-4">
<p class="name-edit-p">ФИО</p> <p class="name-edit-p">ФИО</p>
@ -52,7 +74,7 @@
<p class="name-edit-p">Специализации</p> <p class="name-edit-p">Специализации</p>
<div id="simpleSpecContainer"> <div id="simpleSpecContainer">
<div class="i polsF1 pols-edit disTab -simple-spec-widget" style="display: none"> <div class="polsF1 pols-edit disTab -simple-spec-widget" style="display: none">
<input type="hidden" class="-simple-spec-select" style="width: 100%"> <input type="hidden" class="-simple-spec-select" style="width: 100%">
<input type="hidden" class="-chosen-simple-spec-id" name="{{ form.contractor_specializations.html_name }}"> <input type="hidden" class="-chosen-simple-spec-id" name="{{ form.contractor_specializations.html_name }}">
</div> </div>
@ -230,4 +252,3 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

@ -3,6 +3,19 @@
{% load thumbnail %} {% load thumbnail %}
{% block head_css %}
<style>
.-live-image-delete-parent {position: relative}
.-live-image-delete {
position: absolute;
top: 0;
right: 0;
background-color: white;
}
</style>
{% endblock %}
{% block content %} {% block content %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
@ -19,9 +32,11 @@
<div class="projectsBlock disTab"> <div class="projectsBlock disTab">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="col-lg-3 divCol3 -live-image-upload-container"> <div class="col-lg-3 divCol3 -live-image-upload-container" data-stub-image-url="{% static 'img/profile.jpg' %}">
<div class="avatar"> <div class="avatar">
<div class="avatarInset"> <div class="avatarInset -live-image-delete-parent">
<a href="#" onclick="return false" class="btn close -live-image-delete" style="display: none">&times;</a>
{% if request.user.avatar %} {% if request.user.avatar %}
{% thumbnail request.user.avatar "235x224" crop="center" as avatar %} {% thumbnail request.user.avatar "235x224" crop="center" as avatar %}
<img src="{{ avatar.url }}" alt="profile-image" class="-avatar-image"> <img src="{{ avatar.url }}" alt="profile-image" class="-avatar-image">
@ -32,18 +47,19 @@
</div> </div>
</div> </div>
{# <div class="menuUser upload-img disTab">#} <div class="menuUser upload-img disTab">
{# <div class="upload2 up-l1">#} <div class="upload2 up-l1">
{# <input type="file" name="image" data-url="{% url 'common:live-image-upload-create' %}" class="-live-image-upload">#} <input type="file" name="image" data-url="{% url 'common:live-image-upload-create' %}" class="-live-image-upload">
{# #}
{# <p>Загрузить фотографию</p>#} <p>Загрузить фотографию</p>
{# </div>#} </div>
{# </div>#} </div>
{# #}
{# <div s--tyle="display: none">#} <div {% if not TESTING %}style="display: none"{% endif %}>
{# <input type="text" value="{{ form.live_images.value }}" name="{{ form.live_images.html_name }}" class="-live-image-id">#} <input type="text" name="live_image" class="-live-image-id">
{# </div>#} </div>
</div> </div>
<div class="col-lg-9 divCol9"> <div class="col-lg-9 divCol9">
<div class="col-lg-4"> <div class="col-lg-4">
<p class="name-edit-p">ФИО</p> <p class="name-edit-p">ФИО</p>
@ -171,19 +187,3 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block js_block %}
<script>
{# $('.-live-image-upload').first().fileupload({#}
{# dataType: 'json',#}
{# #}
{# done: function($evt, data) {#}
{# console.log('###################################')#}
{# console.log('Uploading a file...')#}
{# console.log('###################################')#}
{# #}
{# $('.-avatar-image').attr('src', data.result.files[0].thumbnailUrl)#}
{# }#}
{# })#}
</script>
{% endblock %}

@ -61,10 +61,22 @@ class UserProfileEditView(BaseMixin, View):
specs = request.POST.getlist('contractor_specializations') specs = request.POST.getlist('contractor_specializations')
request.POST.setlist('contractor_specializations', _.compact(specs)) # Ignore empty input values request.POST.setlist('contractor_specializations', _.compact(specs)) # Ignore empty input values
form = self.form_class(request.POST, request.FILES, request=request, instance=request.user) form = self.form_class(request.POST, request=request, instance=request.user)
if form.is_valid(): if form.is_valid():
form.save() user = form.save()
live_image = form.cleaned_data.get('live_image')
if live_image:
new_image = ContentFile(live_image.file.read())
new_image.name = live_image.file.name
user.avatar = new_image
user.save()
live_image.file.delete()
live_image.delete()
messages.info(request, 'Пользователь успешно отредактирован') messages.info(request, 'Пользователь успешно отредактирован')
redirect_to = request.POST.get('next') redirect_to = request.POST.get('next')
@ -117,7 +129,19 @@ class UserFinancialInfoEditView(BaseMixin, View):
user = form.save() user = form.save()
fin_info = fin_info_form.save() fin_info = fin_info_form.save()
live_image = form.cleaned_data.get('live_image')
if live_image:
new_image = ContentFile(live_image.file.read())
new_image.name = live_image.file.name
user.avatar = new_image
live_image.file.delete()
live_image.delete()
user.financial_info = fin_info user.financial_info = fin_info
user.save() user.save()
messages.info(request, 'Финансовая информация успешно отредактирована') messages.info(request, 'Финансовая информация успешно отредактирована')

Loading…
Cancel
Save