remotes/origin/PR-39
ArturBaybulatov 9 years ago
commit ba1d5e104c
  1. 4
      api/views.py
  2. 16
      archilance/settings/base.py
  3. 27
      assets/js/chat.js
  4. 2
      chat/admin.py
  5. 29
      chat/filters.py
  6. 2
      chat/serializers.py
  7. 176
      chat/templates/chat_contractor.html
  8. 69
      chat/templates/chat_customer.html
  9. 6
      chat/views.py
  10. 8
      projects/models.py
  11. 13
      projects/serializers.py
  12. 16
      projects/templates/project_detail.html
  13. 2
      templates/partials/base.html
  14. 15
      templates/partials/header.html
  15. 6
      templates/registration/registration_form.html

@ -30,7 +30,7 @@ from common.filters import LocationFilterSet
from chat.models import Message, Notes, Documents
from chat.serializers import MessageSerializer, NoteSerializer, DocumentsSerializer
from chat.filters import MessageFilterSet, NoteFilterSet, DocumentsFilterSet
from chat.filters import MessageFilterSet, NoteFilterSet, DocumentFilterSet
from reviews.models import Review
from reviews.serializers import ReviewSerializer
@ -72,7 +72,7 @@ class ReviewViewSet(ModelViewSet):
class DocumentViewSet(ModelViewSet):
queryset = Documents.objects.all()
serializer_class = DocumentsSerializer
# filter_class = DocumentsFilterSet
filter_class = DocumentFilterSet
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def get_queryset(self):

@ -165,6 +165,7 @@ AUTHENTICATION_BACKENDS = (
'social.backends.twitter.TwitterOAuth',
'social.backends.vk.VKOAuth2',
'social.backends.odnoklassniki.OdnoklassnikiOAuth2',
'social.backends.mailru.MailruOAuth2',
# 'django.contrib.auth.backends.ModelBackend',
'users.backend.EmailOrUsernameModelBackend',
)
@ -184,8 +185,9 @@ SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_KEY = '1247035904'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_SECRET = '9AD83DB399405EEFAE7641BD'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_PUBLIC_NAME = 'CBADEFFLEBABABABA'
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '499898042244-bt7v18v4f46k8qg98n1ne8u2hjtmj0cn.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 's69NCyhSlwY0OuGGT8_dFI7E'
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '54397003678-ejfrg1la2vh2jdjq7fb1upc916kd6djo.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'UOLE-UM9bo2UL7i3TXy_WPa5'
# SOCIAL_AUTH_TWITTER_KEY = 'YAe05K4IYYxHhA6J1mTOdDBjq'
# SOCIAL_AUTH_TWITTER_SECRET = 'iRuYqRRaoGkCD4ip74NICb8FeZMxvM6MZ8HLMbm1jX99o7pcaL'
@ -196,6 +198,10 @@ SOCIAL_AUTH_TWITTER_SECRET = 'WhXRHP6BzNwFS8x94pcaCBwxCSMkAEVm3Rg82XhzUaIqsf2Ur0
SOCIAL_AUTH_VK_OAUTH2_KEY = '5542865'
SOCIAL_AUTH_VK_OAUTH2_SECRET = 'BsOSDhmyNiDte7cMJlVq'
SOCIAL_AUTH_MAILRU_OAUTH2_KEY = 'f7bad5797a375a5eeba6217d64de71f4'
SOCIAL_AUTH_MAILRU_OAUTH2_SECRET = '480fd6d67e9e8625fbc6b6b9a8ec71f0'
SOCIAL_AUTH_VK_OAUTH2_SCOPE = [
'notify',
'friends',
@ -203,9 +209,9 @@ SOCIAL_AUTH_VK_OAUTH2_SCOPE = [
]
# SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
# SOCIAL_AUTH_NEW_USER_REDIRECT_URL = 'http://proekton.com/'
# SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = 'http://proekton.com/'
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/'
SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/'
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',

@ -1,6 +1,6 @@
var SocketHandler = function () {
domain = domain.replace(':' + port, '');
var url = 'ws://' + domain + ':8888/chat/' + userId + '/';
var url = 'ws://' + domain + '/chat/' + userId + '/';
var sock = new WebSocket(url);
var intervalId;
sock.onopen = function () {
@ -192,6 +192,29 @@ $(function () {
});
//Удаление документа
$('.tab-content').on('click','.remove-document', function(e){
e.preventDefault();
var dataId = $(this).attr('data-id');
var _this = $(this);
$.ajax({
url: '/api/documents/' + dataId +'/',
type: 'DELETE',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
dataType: 'json',
success: function(json){
_this.parent().remove();
console.log(json);
},
error: function (e, jqxhr) {
console.log(jqxhr);
}
});
});
// Вытащить сообщения для конактов
$('.user-block').on('click', function () {
@ -228,7 +251,7 @@ $(function () {
console.log(json);
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">' + v.file + '</a><div style="right:-10px;"></divsty></li>';
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">' + v.file + '</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
});
},
error: function (e) {

@ -3,7 +3,7 @@ from .models import Message, Notes, Documents
class MessageAdmin(admin.ModelAdmin):
list_display = ('text', 'sender', 'recipent',)
list_display = ('text', 'sender', 'recipent', 'is_new',)
class NotesAdmin(admin.ModelAdmin):

@ -2,16 +2,16 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter
from .models import Message, Notes, Documents
class DocumentsFilterSet(FilterSet):
file = AllLookupsFilter()
sender = RelatedFilter('users.filters.UserFilterSet')
recipent = RelatedFilter('users.filters.UserFilterSet')
# order = AllLookupsFilter()
# team = AllLookupsFilter()
class Meta:
model = Documents
#
# class DocumentsFilterSet(FilterSet):
# file = AllLookupsFilter()
# # sender = RelatedFilter('users.filters.UserFilterSet')
# # recipent = RelatedFilter('users.filters.UserFilterSet')
# # order = RelatedFilter('projects.filters.OrderFilterSet')
# # order = AllLookupsFilter()
#
# class Meta:
# model = Documents
class MessageFilterSet(FilterSet):
@ -26,6 +26,15 @@ class MessageFilterSet(FilterSet):
model = Message
class DocumentFilterSet(FilterSet):
id = AllLookupsFilter()
# order = RelatedFilter('projects.filters.OrderFilterSet')
class Meta:
model = Documents
class NoteFilterSet(FilterSet):
text = AllLookupsFilter()
created = AllLookupsFilter()

@ -36,7 +36,6 @@ class DocumentsSerializer(ModelSerializer):
return obj.file.url
class MessageSerializer(ModelSerializer):
sender = UserSerializer()
recipent = UserSerializer()
@ -79,4 +78,3 @@ class NoteSerializer(ModelSerializer):
'sender',
'recipent',
)

@ -23,11 +23,11 @@
<a href="#tab2" data-toggle="tab">Заказчики</a>
</li>
{% if team_orders %}
<li role="presentation">
<a href="#tab3" data-toggle="tab">Исполнители</a>
</li>
{% endif %}
</ul>
</div>
</div>
@ -142,9 +142,9 @@
<div class="col-lg-6 commChat">
<div id="message-chat-order-space"></div>
<form id="chat-order-add">
<input type="text" id="orderId" name="orderId">
<input type="text" id="senderId" name="senderId" value="{{ request.user.pk }}">
<input type="text" id="recipentId" name="recipentId" value="">
<input type="hidden" id="orderId" name="orderId">
<input type="hidden" id="senderId" name="senderId" value="{{ request.user.pk }}">
<input type="hidden" id="recipentId" name="recipentId" value="">
<textarea id="chat" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p>
<div class="bunChat">
@ -204,6 +204,15 @@
<!-- Arbitration add -->
{% include 'arbitration_modal.html' %}
<!-- -->
<div class="col-lg-12 documentsChat">
<p>Входящие документы</p>
<ul id="documentOrderSpace"></ul>
{# <a href="javascript:void(0)">#}
{# Распечатать с помощью ресурса#}
{# </a>#}
</div>
<div class="textAreaBlock2 box-sizing disTab">
<ul class="notes-block">
</ul>
@ -220,7 +229,7 @@
</div>
<!-- End block Tab2-->
{% if team_orders %}
<!-- Tab3 groups block -->
<div class="chatBlock disTab tab-pane fade" id="tab3">
<div class="col-lg-3 wrMessages">
@ -262,13 +271,47 @@
</div>
</div>
{% endfor %}
{% for yteam in your_teams %}
<div class="team-block orderBlock box-sizing" data-id="{{ yteam.pk }}">
<span class="dimovChat"></span>
<p class="titleOB">
{{ yteam }}
</p>
<div class="hideOBB disTab">
<p class="pOB">
<span>Владелец группы:</span> {{ yteam.owner }}
</p>
<ul class="listChat1">
{% for tuser in yteam.contractors.all %}
<li>{{ tuser }}</li>
{% endfor %}
</ul>
<p class="pOB">
<span>Чаты:</span>
{% if request.user.pk != torder.team.owner.pk %}
<span class="team-chat-user"
data-id="{{ torder.team.owner.pk}}">{{ torder.team.owner.username }},</span>
{% endif %}
{% for tuser in yteam.contractors.all %}
{% if request.user.pk != tuser.pk %}
<span class="team-chat-user"
data-id="{{ tuser.pk }}">{{ tuser.username }},</span>
{% endif %}
{% endfor %}
</p>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="col-lg-6 commChat">
<div id="message-chat-team-space"></div>
<form id="team-chat-form">
<input type="hidden" name="sender" id="senderTeamId" value="{{ request.user.pk }}"/>
<input type="hidden" name="recipent" id="recipenTeamtId" value=""/>
<input type="hidden" name="recipent" id="recipentTeamId" value=""/>
<input type="hidden" name="order" id="orderTeamId">
<input type="hidden" name="team" id="teamId" value=""/>
<input type="hidden" name="document-send" id="documentSendIds"/>
@ -292,7 +335,7 @@
</div>
</div>
<!-- End block Tab3-->
{% endif %}
<!-- order-info -->
{% include 'order_info.html' %}
@ -322,15 +365,20 @@
}, 1000);
var url = '/chat/create/';
$("#upload-document-team").bind('fileuploadsubmit', function (e, data) {
data.formData = {
sender: $("#team-chat-form #senderTeamId").val(),
recipent: $("#team-chat-form #recipentTeamId").val(),
order: $("#team-chat-form #orderTeamId").val(),
team: $("#team-chat-form #teamId").val(),
}
console.log(data.formData);
});
//Загрузка документов
$('#upload-document-team').fileupload({
url: url,
formData: {
sender: $("#team-chat-form #senderId").val(),
recipent: $("#team-chat-form #recipentId").val(),
team: $("#team-chat-form #teamId").val(),
order: $("#team-chat-form #orderId").val(),
},
crossDomain: false,
beforeSend: function (xhr, settings) {
$('#progress .progress-bar').css(
@ -402,10 +450,48 @@
});
// Согласование этапов
$("#order-stages").on('click', "#cancel-stages", function (e) {
e.preventDefault();
$(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id');
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "status=cancel_approve",
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var orderId = $(this).attr('data-order-id');
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": $(this).attr('data-sender-id'),
"recipent_id": $(this).attr('data-recipent-id'),
"order_id": orderId,
"msg": "Исполнитель отказался от текущих этапов " + orderId,
}
});
});
$(".team-chat-user").on('click', function (e) {
e.stopPropagation();
var recipentId = $(this).attr('data-id');
$("#team-chat-form #recipentId").val(recipentId);
$("#team-chat-form #recipentTeamId").val(recipentId);
});
$(".team-order-block").on('click', function () {
@ -418,7 +504,7 @@
var teamId = $(this).attr('data-team-id');
var orderId = $(this).attr('data-order-id');
$("#team-chat-form #teamId").val(teamId);
$("#team-chat-form #orderId").val(orderId);
$("#team-chat-form #orderTeamId").val(orderId);
var inbox = document.getElementById('message-chat-team-space');
inbox.innerHTML = '';
@ -464,6 +550,7 @@
$("#targetCustomerId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId);
var docList = document.getElementById('documentOrderSpace');
var inbox = document.getElementById('message-chat-order-space');
inbox.innerHTML = '';
@ -487,6 +574,24 @@
}
});
$.ajax({
url:'/api/documents',
type: 'GET',
data:{
csrfmiddlewaretoken: csrftoken,
'order': orderId
},
dataType: 'json',
success: function (json){
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">'+ v.file+'</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
});
},
error: function(e){
console.log(e);
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
@ -508,7 +613,6 @@
type: 'GET',
data:{csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function(data){
var htmlInbox = "";
var stagesReservedHtml = "";
@ -522,7 +626,7 @@
if (v.status == "completed"){
stagesCompleted.push(v);
}
if(v.status == "not_agreed"){
if(v.status == "not_agreed" || v.status == "send_approve"){
statusNotAgreed = true;
}
if(!data.secure){
@ -544,6 +648,23 @@
}
var statusName = '';
switch(v.status){
case 'not_agreed':
statusName = 'Не согласован';
break;
case 'send_approve':
statusName = 'На согласовании';
break;
case 'cancel_approve':
statusName = 'Исполнитель отказался';
break;
case 'in_process':
statusName = 'В процессе';
break;
case 'completed':
statusName = 'Завершен';
break;
}
if (v.status == 'completed'){
statusName = 'Завершен';
}
@ -557,7 +678,10 @@
if (statusNotAgreed) {
htmlInbox += '<div class="textAreaBlock2 FFD box-sizing disTab">' +
'<a id="approve-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">согласовать</a></div>';
' data-order-id="' + orderId + '" href="#">согласовать</a>' +
'<a id="cancel-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">отказаться</a>' +
'</div>';
}
}
@ -661,18 +785,17 @@
});
//Добавить сообщение для исполнителей в группе
$("#add-team-chat-message").on('click', function () {
$("#add-team-chat-message").on('click', function (e) {
e.preventDefault();
var chatMessage = $("#team-chat-form #chatText").val();
var recipentId = $("#team-chat-form #recipentId").val();
var senderId = $("#team-chat-form #senderId").val();
var recipentId = $("#team-chat-form #recipentTeamId").val();
var senderId = $("#team-chat-form #senderTeamId").val();
var teamId = $("#team-chat-form #teamId").val();
var orderId = $("#team-chat-form #orderId").val();
var orderId = $("#team-chat-form #orderTeamId").val();
var documentSendIds = $("#documentSendIds").val();
console.log(documentSendIds);
var teamDocumentIds = documentSendIds.split(';');
teamDocumentIds.pop();
console.log(teamDocumentIds);
socket.add_team_message({
"format_type": "add_message_team",
"data": {
@ -686,6 +809,7 @@
$("#team-chat-form #chatText").val("");
$("#document-send").html("");
$("#documentSendIds").val("");
});

@ -89,8 +89,10 @@
{# <a href="javascript:void(0)">#}
{# Распечатать с помощью ресурса#}
{# </a>#}
</div>
</div>
<div class="textAreaBlock2 box-sizing disTab">
<p>Заметки</p>
<ul class="contractor-notes-block">
</ul>
<form id="add-form-contractor-note">
@ -337,6 +339,7 @@
data:{csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function(data){
var isReviewLeave = data.has_user_review;
var stagesResults = data.stages;
var stageCount = stagesResults.length;
if (stageCount == 0) {
@ -352,12 +355,13 @@
if (stageCount == 0) {
htmlInboxStage += '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">1</span></p><form class="new-stages-form" id="stage-form">' +
'<label for="">Название</label><input class="form-control" name="name" type="text" />' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text" />' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '"/>' +
'<label for="">Срок</label><input class="term-picker form-control datepicker" name="term" type="text" />' +
'<label for="">Результат</label><input class="form-control" name="result" type="text" />' +
'<input class="form-control" name="pos" value="1" type="hidden" />' +
'<label for="">Название</label><input class="form-control" name="name" type="text">' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text">' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '">' +
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<label for="">Срок</label><input class="term-picker form-control datepicker" name="term" type="text">' +
'<label for="">Результат</label><input class="form-control" name="result" type="text">' +
'<input class="form-control" name="pos" value="1" type="hidden">' +
'</form></div>';
}
var statusNotAgreed = true;
@ -384,19 +388,20 @@
stagePaidCount +=1;
}
if (v.status == "not_agreed") {
if (v.status == "not_agreed" || v.status == 'cancel_approve' || v.status == 'send_approve') {
htmlInbox += '<div class="numberStepp box-sizing">' +
'<p>Этап</p><form class="update-stages-form" data-stage-id="' + v.id + '" id="stage-form-' + v.pos + '">' +
'<label for="">Название</label><input class="form-control" type="text" name="name" value="' + v.name + '" />' +
'<label for="">Цена</label><input class="form-control" type="text" name="cost" value="' + v.cost + '" />' +
'<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '"/>' +
'<label for="">Название</label><input class="form-control" type="text" name="name" value="' + v.name + '">' +
'<label for="">Цена</label><input class="form-control" type="text" name="cost" value="' + v.cost + '" >' +
'<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '">' +
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<label for="">Срок</label><input class="term-picker form-control datepicker" type="text" name="term" value="' + v.term + '" />' +
'<label for="">Результат</label><input class="form-control" type="text" name="result" value="' + v.result + '" />' +
'<label for="">Результат</label><input class="form-control" type="text" name="result" value="' + v.result + '" >' +
'</form></div>';
} else {
statusNotAgreed = false;
htmlInboxStage = "";
var statusName = '';
var statusName = "";
if (v.status == 'completed'){
statusName = 'Завершен';
}
@ -464,17 +469,12 @@
$("#reserveSpace").hide();
}
if((stagesCompleted.length == stagesResults.length) && (stagesCompleted.length > 0)){
if((stagesCompleted.length == stagesResults.length) && (stagesCompleted.length > 0) && (!isReviewLeave)){
$("#leaveReview").show();
console.log("Все этапы завершены");
}else {
$("#leaveReview").hide();
}
if (data.status == 'completed'){
$("#leaveReview").hide();
}
$(".stages-paid").html(stagesReservedHtml);
});
@ -593,17 +593,12 @@
}
});
{# setTimeout(function () {#}
{# getStages(currentOrderId,userId,currentRecipentId,secureOrder);#}
{##}
{# }, 1000);#}
});
//Изменение счетчика
$('#order-stages-tab').on('change', '#countStage', function () {
var countStage = parseInt($(this).val());
var currentCountStage = $(".numberStepp").length;
var currentCountStage = $("#order-stages .numberStepp").length;
if ((countStage<1) || isNaN(countStage)) {
countStage = 1;
$('#order-stages-tab #countStage').val(currentCountStage);
@ -611,23 +606,23 @@
if (countStage > currentCountStage) {
for (var jj = currentCountStage; jj < countStage; jj++) {
var pos = jj + 1;
var lastFormStage = $(".numberStepp").last();
var lastFormStage = $("#order-stages .numberStepp").last();
var orderId = lastFormStage.find('.orderStagesInput').val();
var addFormTemplate = '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">' + pos + '</span></p><form class="new-stages-form" id="stage-form">' +
'<label for="">Название</label><input class="form-control" name="name" type="text" />' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text" />' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '" />' +
'<label for="">Срок</label><input class="term-picker form-control datepicker" name="term" type="text" />' +
'<label for="">Результат</label><input class="form-control" name="result" type="text" />' +
'<input class="form-control" name="pos" value="' + pos + '" type="hidden" />'
'</form></div>';
'<label for="">Название</label><input class="form-control" name="name" type="text">' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text">' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '">' +
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<label for="">Срок</label><input class="term-picker form-control datepicker" name="term" type="text">' +
'<label for="">Результат</label><input class="form-control" name="result" type="text">' +
'<input class="form-control" name="pos" value="' + pos + '" type="hidden"></form></div>';
lastFormStage.after(addFormTemplate);
}
} else if (countStage < currentCountStage) {
var ii = currentCountStage;
$($(".numberStepp").get().reverse()).each(function () {
$($("#order-stages .numberStepp").get().reverse()).each(function () {
var currenFormName = ($(this).find('form').attr('class'));
if (ii > countStage) {
$(this).remove();
@ -639,6 +634,8 @@
}
});
// Для заказов все вытащить
$('.order-block').on('click', function () {
$("#chat-order-add").css("display", "block");
@ -675,10 +672,8 @@
},
dataType: 'json',
success: function (json){
console.log(json);
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">'+ v.file+'</a></li>';
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">'+ v.file+'</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
});
},
error: function(e){

@ -69,6 +69,7 @@ class ChatUserView(LoginRequiredMixin, View):
if request.user.is_owner_team():
team_ids.append(request.user.team.pk)
team_orders = request.user.team.orders.all()
teams = Team.objects.filter(contractors__id=request.user.pk).all()
else:
teams = Team.objects.filter(contractors__id=request.user.pk).all()
team_orders = Order.objects.filter(team_id__in=[team.pk for team in teams]).all()
@ -89,14 +90,13 @@ class ChatUserView(LoginRequiredMixin, View):
chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)).order_by(
'created')
your_teams = teams
self.template_name = 'chat_contractor.html'
return render(request, self.template_name, {'orders': orders,
'contacts_users': contacts_users,
'chat_messages': chat_messages,
'team_orders': team_orders,
'your_teams': your_teams,
})

@ -240,9 +240,11 @@ class Arbitration(models.Model):
STATUSES = (
('not_agreed','Не согласован'),
('in_process','В процессе'),
('completed','Завершен'),
('not_agreed', 'Не согласован'),
('send_approve', 'На согласовании'),
('cancel_approve', 'Исполнитель отказался'),
('in_process', 'В процессе'),
('completed', 'Завершен'),
)

@ -123,9 +123,16 @@ class OrderSerializer(ModelSerializer):
)
def get_has_user_review(self,obj):
# obj.project.
print(self.context['request'].user)
return "yes"
curr_user = self.context['request'].user
if curr_user.is_customer():
return curr_user.customer_reviews.filter(project=obj.project).exists()
elif curr_user.is_contractor():
if obj.team is None and obj.contractor:
return curr_user.contractor_reviews.filter(project=obj.project).exists()
elif curr_user.team:
return curr_user.team.team_reviews.filter(project=obj.project).exists()
else:
return False
class PortfolioPhotoSerializer(ModelSerializer):

@ -27,7 +27,9 @@
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if project.customer.avatar %}
<img src="{{ project.customer.avatar.url }}" alt="execitor-image">
{% thumbnail project.customer.avatar "125x125" crop="center" as im %}
<img src="{{ im.url }}" alt="execitor-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}
@ -517,7 +519,9 @@
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if answer.author.avatar %}
<img src="{{ answer.author.avatar.url }}" alt="execitor-image">
{% thumbnail answer.author.avatar "125x125" crop="center" as im %}
<img src="{{ im.url }}" alt="execitor-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}
@ -677,7 +681,9 @@
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if answer.author.avatar %}
<img src="{{ answer.author.avatar.url }}" alt="execitor-image">
{% thumbnail answer.author.avatar "125x125" crop="center" as im %}
<img src="{{ im.url }}" alt="execitor-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}
@ -839,7 +845,9 @@
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if answer.author.avatar %}
<img src="{{ answer.author.avatar.url }}" alt="execitor-image">
{% thumbnail answer.author.avatar "125x125" crop="center" as im %}
<img src="{{ im.url }}" alt="execitor-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}

@ -89,7 +89,7 @@
if ((queryString.indexOf('/chat') != 0) && (queryString.indexOf('/users/contractor-office/510/work-projects') != 0)) {
domain = domain.replace(':' + port, '');
var url = 'ws://' + domain + ':8888/chat/' + userId + '/';
var url = 'ws://' + domain + '/chat/' + userId + '/';
var sock = new WebSocket(url);
var intervalId;
sock.onopen = function () {

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

@ -83,6 +83,12 @@
</a>
</div>
{# <div class="pull-left -social -vk">#}
{# <a href="{% url 'social:begin' 'mailru-oauth2' %}">#}
{# <img src="http://nepesh.com/static/img/social/vk.png" alt="vk">#}
{# </a>#}
{# </div>#}
<div class="pull-left -social -ok">
<a href="{% url 'social:begin' 'odnoklassniki-oauth2' %}">
<img src="http://nepesh.com/static/img/social/ok.gif" alt="yt">

Loading…
Cancel
Save