remotes/origin/PR-39
ArturBaybulatov 9 years ago
commit 0850b10273
  1. 121
      assets/js/chat.js
  2. 31
      assets/js/chat_contractor.js
  3. 126
      assets/js/chat_customer.js
  4. 1
      chat/chat.py
  5. 41
      chat/templates/chat_contractor.html
  6. 187
      chat/templates/chat_customer.html
  7. 2
      chat/templates/reverse_stage_modal.html
  8. 18
      chat/templates/review_add_modal.html
  9. 9
      chat/views.py
  10. 12
      reviews/serializers.py
  11. 15
      users/templatetags/user_tags.py

@ -184,7 +184,6 @@ function dialog (message, yesCallback, notCallback) {
$("a[href='#tab1']").trigger('click'); $("a[href='#tab1']").trigger('click');
} }
// Информация о заказе // Информация о заказе
$(".messageBlock").on('click','.full-order-info', function (e) { $(".messageBlock").on('click','.full-order-info', function (e) {
e.preventDefault(); e.preventDefault();
@ -322,6 +321,7 @@ function dialog (message, yesCallback, notCallback) {
// Вытащить сообщения для конактов // Вытащить сообщения для конактов
$('.user-block').on('click', function () { $('.user-block').on('click', function () {
var newCount = parseInt($("#count-tab-contact").text());
var contactId = $(this).attr('data-id'); var contactId = $(this).attr('data-id');
location.hash = '#user' + contactId; location.hash = '#user' + contactId;
$("#contact-chat-form #recipentContactId").val(contactId); $("#contact-chat-form #recipentContactId").val(contactId);
@ -336,6 +336,9 @@ function dialog (message, yesCallback, notCallback) {
var sumSenderRecipent = parseInt(userId) + parseInt(contactId); var sumSenderRecipent = parseInt(userId) + parseInt(contactId);
$("#message-chat-space").removeClass().addClass("contact-space" + sumSenderRecipent); $("#message-chat-space").removeClass().addClass("contact-space" + sumSenderRecipent);
var currNewCount = parseInt($(".contact-count-" + sumSenderRecipent).text());
var resCount = newCount - currNewCount;
$("#count-tab-contact").text(newCount - currNewCount);
$(".contact-count-" + sumSenderRecipent).text(0); $(".contact-count-" + sumSenderRecipent).text(0);
var docList = document.getElementById('documentSpace'); var docList = document.getElementById('documentSpace');
inbox.innerHTML = ''; inbox.innerHTML = '';
@ -758,6 +761,7 @@ function dialog (message, yesCallback, notCallback) {
var related = $(e.relatedTarget); var related = $(e.relatedTarget);
var relatedType = related.attr('data-review-type'); var relatedType = related.attr('data-review-type');
$('input[name="type"]').filter('[value="'+ relatedType+'"]').prop("checked", true); $('input[name="type"]').filter('[value="'+ relatedType+'"]').prop("checked", true);
$("#text-new").val("");
}); });
// Добавление отзыва // Добавление отзыва
@ -776,15 +780,19 @@ function dialog (message, yesCallback, notCallback) {
success: function (json) { success: function (json) {
console.log(json); console.log(json);
$("#review-add").modal('hide'); $("#review-add").modal('hide');
//socket.send_stages_approve({ $("#leaveReview").hide();
// "format_type": "approve_stages", var currOrder = json.project;
// "data": { var currRecipent = json.target_user;
// "sender_id": userId,
// "recipent_id": '', socket.send_stages_approve({
// "order_id": '', "format_type": "approve_stages",
// "msg": "Отзыв добавлен", "data": {
// } "sender_id": userId,
//}); "recipent_id": currRecipent,
"order_id": currOrder,
"msg": "Отзыв добавлен",
}
});
}, },
error: function (e) { error: function (e) {
console.log('error'); console.log('error');
@ -792,6 +800,99 @@ function dialog (message, yesCallback, notCallback) {
} }
}); });
}); });
// Нажимаем на кнопку архивные сообщения
$("#trashed-button").on('click',function(e){
e.preventDefault();
var state = $(this).attr('data-show');
var trashedOrderHtml = "";
if (state == 'true') {
$(this).attr('data-show','false');
$(this).text("Скрыть архивные заказы");
$("#archive-space").show();
$("#show-archive-label").show();
//$.ajax({
// url: '/api/orders/',
// type: 'GET',
// dataType: 'json',
// success: function (json) {
// console.log(json.results);
// $.each(json.results, function (i, v) {
//
// var temp = '<div data-id="'+ v.id +'" class="trashedOrderBlock box-sizing"><span class="dimovChat"></span>' +
// '<p class="titleOB">' + v.project.name + '</p><div class="hideOBB"><p class="pOB">' +
// '<span>Исполнитель:</span>'+ v.contractor_name +' </p>' +
// '<a href="#" class="linkChat11 full-order-info">' +
// '<span class="glyphicon glyphicon-info-sign" aria-hidden="true">' +
// '</span>Полное описание заказа </a></div></div>';
//
// trashedOrderHtml += temp;
// });
// $("#trashed-orders").html(trashedOrderHtml);
//
// },
// error: function (e, jqxhr) {
// console.log(e);
// }
//});
}else {
$(this).attr('data-show','true');
$(this).text("Показать архивные заказы");
$("#archive-space").hide();
$("#show-archive-label").hide();
}
});
// Нажимаем на заказ в архмвных заказах
$(".messageBlock").on('click','.trashedOrderBlock',function(){
$("#chat-order-add").css("display", "none");
$('.order-block, .trashedOrderBlock').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var inbox = document.getElementById('message-chat-order-space');
var docList = document.getElementById('documentOrderSpace');
inbox.innerHTML = '';
docList.innerHTML = '';
var orderId = $(this).attr('data-id');
location.hash = '#order' + orderId;
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team__isnull': 'true'},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
var senderName = 'Вы';
var className = 'youChat';
if (v.sender.id !== userId) {
senderName = v.sender.username;
className = '';
}
inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p><span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$("#order-stages").html("");
$("#completeWork").hide();
$("#add-form-order-note").hide();
$("#reserveSpace").hide();
});
}); });

@ -78,6 +78,7 @@ $(function () {
$(".stage-block-approve").each(function () { $(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id'); var stageId = $(this).attr('data-id');
$.ajax({ $.ajax({
//async: false,
url: '/api/stages/' + stageId + '/', url: '/api/stages/' + stageId + '/',
type: 'PATCH', type: 'PATCH',
beforeSend: function (xhr) { beforeSend: function (xhr) {
@ -107,8 +108,20 @@ $(function () {
} }
}); });
$('body').append('<div class="modal" id="popupOk" role="dialog" aria-labelledby="myModalLabel">' +
'<div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header">' +
'<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
'<span aria-hidden="true">&times;</span></button>' +
'<h4 class="modal-title" id="myModalLabel">Уведомление</h4>' +
'</div><div class="modal-body">Вы согласовали этапы</div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-default" data-dismiss="modal">ОК</button>' +
'</div></div></div></div>');
$('#popupOk').modal('show');
}.bind(orderId, senderId, recipentId), caption); }.bind(orderId, senderId, recipentId), caption);
}); });
// Отказаться от этапов // Отказаться от этапов
@ -348,6 +361,15 @@ $(function () {
location.hash = '#order' + orderId; location.hash = '#order' + orderId;
var recipentId = $(this).attr('data-recipent-id'); var recipentId = $(this).attr('data-recipent-id');
var projectId = $(this).attr('data-project-id'); var projectId = $(this).attr('data-project-id');
var teamCurrentId = parseInt($(this).attr('data-team-id'));
if (teamCurrentId>0){
$("#fromTeamId").val(teamCurrentId);
$("#fromContractorId").val("");
}else {
$("#fromTeamId").val("")
$("#fromContractorId").val(userId);
}
$("#chat-order-add #orderId").val(orderId); $("#chat-order-add #orderId").val(orderId);
$("#add-form-order-note #orderNote").val(orderId); $("#add-form-order-note #orderNote").val(orderId);
@ -534,12 +556,15 @@ $(function () {
} else { } else {
$("#completeWork").hide(); $("#completeWork").hide();
} }
if (!data.has_user_review) {
if ((stagesCompleted.length == stagesResults.length) && stagesCompleted.length > 0 && !data.has_user_review) { if ((stagesCompleted.length == stagesResults.length) && stagesCompleted.length > 0) {
$("#leaveReview").show(); $("#leaveReview").show();
}else{ } else {
$("#leaveReview").hide(); $("#leaveReview").hide();
} }
}else{
$("#leaveReview").hide();
}
}); });

@ -46,6 +46,12 @@ $(function () {
$("#choiceWayOrder").attr('data-stages-ids', stagesIds); $("#choiceWayOrder").attr('data-stages-ids', stagesIds);
$("#stagesSelect").selectpicker({
style: 'btn-info',
size: 4
});
} }
}); });
@ -213,7 +219,7 @@ $(function () {
'</div></div>'; '</div></div>';
if (stage.close_contractor) { if (stage.close_contractor) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-order-id="' + orderId + '" data-sender-id="{{ request.user.pk }}"' + stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-order-id="' + orderId + '" data-sender-id="'+ userId +'"' +
' data-recipent-id="' + recipentId + '" data-stage-id="' + stage.id + '">Закрыть этап ' + stage.pos + '</a></div>'; ' data-recipent-id="' + recipentId + '" data-stage-id="' + stage.id + '">Закрыть этап ' + stage.pos + '</a></div>';
} }
@ -286,6 +292,7 @@ $(function () {
$.ajax({ $.ajax({
url: '/api/orders/' + currentOrderId + '/', url: '/api/orders/' + currentOrderId + '/',
type: 'PATCH', type: 'PATCH',
beforeSend: function (xhr) { beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')) xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
}, },
@ -305,6 +312,7 @@ $(function () {
var _this = $(this); var _this = $(this);
console.log($(this).serialize()); console.log($(this).serialize());
$.ajax({ $.ajax({
async: false,
url: '/api/stages/', url: '/api/stages/',
type: 'POST', type: 'POST',
beforeSend: function (xhr) { beforeSend: function (xhr) {
@ -333,8 +341,9 @@ $(function () {
$(".update-stages-form").each(function (i, v) { $(".update-stages-form").each(function (i, v) {
var _this = $(this); var _this = $(this);
var currentStageId = parseInt($(this).attr('data-stage-id')); var currentStageId = parseInt($(this).attr('data-stage-id'));
console.log($(this).serialize()); console.log($(this).serialize());
$.ajax({ $.ajax({
async: false,
url: '/api/stages/' + currentStageId + '/', url: '/api/stages/' + currentStageId + '/',
type: 'PUT', type: 'PUT',
beforeSend: function (xhr) { beforeSend: function (xhr) {
@ -367,7 +376,17 @@ $(function () {
"msg": "Этапы для заказа " + currentOrderId + " изменены", "msg": "Этапы для заказа " + currentOrderId + " изменены",
} }
}); });
$.jGrowl("Этапы для заказа изменены и отправлены исполнителю", { life: 15000}); $('body').append('<div class="modal" id="popupOk" role="dialog" aria-labelledby="myModalLabel">' +
'<div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header">' +
'<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
'<span aria-hidden="true">&times;</span></button>' +
'<h4 class="modal-title" id="myModalLabel">Уведомление</h4>' +
'</div><div class="modal-body">Этапы отправлены исполнителю для согласования</div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-default" data-dismiss="modal">ОК</button>' +
'</div></div></div></div>');
$('#popupOk').modal('show');
//$.jGrowl("Этапы для заказа изменены и отправлены исполнителю", { life: 15000});
}); });
@ -410,97 +429,10 @@ $(function () {
} }
}); });
// Нажимаем на кнопку архивные сообщения
$("#trashed-button").on('click',function(e){
e.preventDefault();
var state = $(this).attr('data-show');
var trashedOrderHtml = "";
if (state == 'true') {
$(this).attr('data-show','false');
$(this).text("Скрыть архивные заказы");
$.ajax({
url: '/api/orders/',
type: 'GET',
dataType: 'json',
success: function (json) {
console.log(json.results);
$.each(json.results, function (i, v) {
var temp = '<div data-id="'+ v.id +'" class="trashedOrderBlock box-sizing"><span class="dimovChat"></span>' +
'<p class="titleOB">' + v.project.name + '</p><div class="hideOBB"><p class="pOB">' +
'<span>Исполнитель:</span>'+ v.contractor_name +' </p>' +
'<a href="#" class="linkChat11 full-order-info">' +
'<span class="glyphicon glyphicon-info-sign" aria-hidden="true">' +
'</span>Полное описание заказа </a></div></div>';
trashedOrderHtml += temp;
});
$("#trashed-orders").html(trashedOrderHtml);
},
error: function (e, jqxhr) {
console.log(e);
}
});
}else {
$(this).attr('data-show','true');
$(this).text("Показать архивные заказы");
$("#trashed-orders").html("");
}
});
// Нажимаем на заказ в архмвных заказах
$(".messageBlock").on('click','.trashedOrderBlock',function(){
$("#chat-order-add").css("display", "none");
$('.order-block, .trashedOrderBlock').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var inbox = document.getElementById('message-chat-order-space');
var docList = document.getElementById('documentOrderSpace');
inbox.innerHTML = '';
docList.innerHTML = '';
var orderId = $(this).attr('data-id');
location.hash = '#order' + orderId;
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team__isnull': 'true'},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
var senderName = 'Вы';
var className = 'youChat';
if (v.sender.id !== userId) {
senderName = v.sender.username;
className = '';
}
inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p><span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$("#order-stages").html("");
$("#completeWork").hide();
$("#add-form-order-note").hide();
$("#reserveSpace").hide();
});
// Для заказов все вытащить // Для заказов все вытащить
$('.order-block').on('click', function () { $('.order-block').on('click', function () {
var newCount = parseInt($("#count-tab-order").text());
$("#chat-order-add").css("display", "block"); $("#chat-order-add").css("display", "block");
$("#add-form-order-note").css("display", "block"); $("#add-form-order-note").css("display", "block");
$("#formsetStage").css("display", "block"); $("#formsetStage").css("display", "block");
@ -516,12 +448,22 @@ $(function () {
var recipentId = $(this).attr('data-recipent-id'); var recipentId = $(this).attr('data-recipent-id');
var secureOrder = $(this).attr('data-secure-deal'); var secureOrder = $(this).attr('data-secure-deal');
secureOrder = Boolean(secureOrder); secureOrder = Boolean(secureOrder);
var teamCurrentId = parseInt($(this).attr('data-team-id'));
if (teamCurrentId>0){
$("#targetTeamId").val(teamCurrentId);
$("#targetContractorId").val("");
}else {
$("#targetTeamId").val("")
$("#targetContractorId").val(recipentId);
}
$("#chat-order-add #orderId").val(orderId); $("#chat-order-add #orderId").val(orderId);
$("#add-form-order-note #orderNote").val(orderId); $("#add-form-order-note #orderNote").val(orderId);
$("#orderArbitrationId").val(orderId); $("#orderArbitrationId").val(orderId);
$("#projectReviewId").val(projectId); $("#projectReviewId").val(projectId);
$("#reserve-button").attr('data-order-id', orderId); $("#reserve-button").attr('data-order-id', orderId);
$("#targetContractorId").val(recipentId);
$("#chat-order-add #recipentId").val(recipentId); $("#chat-order-add #recipentId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId); $("#add-form-order-note #recipentNote").val(recipentId);
$(".orderStagesInput").val(orderId); $(".orderStagesInput").val(orderId);

@ -30,6 +30,7 @@ class ChatHandler(websocket.WebSocketHandler):
# @gen.coroutine # @gen.coroutine
def on_message(self, message): def on_message(self, message):
parsed = escape.json_decode(message) parsed = escape.json_decode(message)
print(parsed)
if 'dummy' in parsed: if 'dummy' in parsed:
return return

@ -17,15 +17,15 @@
<ul class="nav nav-tabs nav-justified"> <ul class="nav nav-tabs nav-justified">
<li role="presentation"> <li role="presentation">
<a href="#tab1" data-toggle="tab">Личные<span class="count-tab">{{ contacts_users_count }}</span></a> <a href="#tab1" data-toggle="tab">Личные<span class="count-tab" id="count-tab-contact">{{ contacts_users_count }}</span></a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#tab2" data-toggle="tab">Заказчики<span class="count-tab">{{ orders_ms_count }}</span></a> <a href="#tab2" data-toggle="tab">Заказчики<span class="count-tab" id="count-tab-order">{{ orders_ms_count }}</span></a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#tab3" data-toggle="tab">Исполнители,Группы<span class="count-tab">{{ teams_ms_count }}</span></a> <a href="#tab3" data-toggle="tab">Исполнители,Группы<span class="count-tab" id="count-tab-team">{{ teams_ms_count }}</span></a>
</li> </li>
</ul> </ul>
@ -123,7 +123,7 @@
<p>Заказы</p> <p>Заказы</p>
{% for order in orders %} {% for order in orders %}
<div class="orderBlock box-sizing order-block" data-project-id="{{ order.project.id }}" <div class="orderBlock box-sizing order-block" data-project-id="{{ order.project.id }}"
id="orderBlock{{ order.id }}" data-recipent-id="{{ order.project.customer.pk }}" data-id="{{ order.id }}"> id="orderBlock{{ order.id }}" data-team-id="{% if order.team %}{{ order.team.pk }}{% else %}0{% endif %}" data-recipent-id="{{ order.project.customer.pk }}" data-id="{{ order.id }}">
<span class="dimovChat"></span> <span class="dimovChat"></span>
<p class="titleOB">{{ order }}</p> <p class="titleOB">{{ order }}</p>
<div class="hideOBB"> <div class="hideOBB">
@ -136,6 +136,39 @@
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
{% if archive_orders %}
<div class="textAreaBlock2 FFD box-sizing disTab">
<a href="#" data-show="true" id="trashed-button">Показать архивные заказы</a>
</div>
<p id="show-archive-label" style="display: none;">Архивные заказы</p>
<div id="archive-space" style="display:none;">
<div id="trashed-orders">
{% for order in archive_orders %}
<div data-id="{{ order.id }}" class="trashedOrderBlock box-sizing">
<span class="dimovChat"></span>
<p class="titleOB"> {{ order.project.name }}</p>
<div class="hideOBB"><p class="pOB">
<span>Исполнитель:
{% if order.contractor %}
{{ order.contractor.get_full_name }}
{% else %}
{{ order.team.name }}
{% endif %}
</span>
</p>
<a href="#" class="linkChat11 full-order-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Полное описание заказа
</a>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div> </div>
</div> </div>

@ -15,10 +15,12 @@
<div class="profileTabs2"> <div class="profileTabs2">
<ul class="nav nav-tabs nav-justified"> <ul class="nav nav-tabs nav-justified">
<li role="presentation"> <li role="presentation">
<a href="#tab1" data-toggle="tab">Личные<span class="count-tab">{{ contacts_users_count }}</span></a> <a href="#tab1" data-toggle="tab">Личные<span
class="count-tab" id="count-tab-contact">{{ contacts_users_count }}</span></a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#tab2" data-toggle="tab">Исполнители<span class="count-tab">{{ orders_ms_count }}</span> <a href="#tab2" data-toggle="tab">Исполнители<span
class="count-tab" id="count-tab-order">{{ orders_ms_count }}</span>
</a> </a>
</li> </li>
</ul> </ul>
@ -27,13 +29,14 @@
</div> </div>
{% include 'dialog_delete.html' %} {% include 'dialog_delete.html' %}
<div class="tab-content"> <div class="tab-content">
<!-- Tab1 (contacts block)--> <!-- Tab1 (contacts block)-->
<div class="chatBlock disTab tab-pane fade in" id="tab1"> <div class="chatBlock disTab tab-pane fade in" id="tab1">
<div class="col-lg-3 wrMessages"> <div class="col-lg-3 wrMessages">
<div class="messageBlock box-sizing disTab"> <div class="messageBlock box-sizing disTab">
<p>Контакты</p> <p>Контакты</p>
{% for contact in contacts_users %} {% for contact in contacts_users %}
<div class="message messd user-block" id="userBlock{{ contact.pk }}" data-id="{{ contact.pk }}"> <div class="message messd user-block" id="userBlock{{ contact.pk }}"
data-id="{{ contact.pk }}">
<div class="imgMess"> <div class="imgMess">
{% if contact.avatar %} {% if contact.avatar %}
{% thumbnail contact.avatar "60x60" crop="center" as im %} {% thumbnail contact.avatar "60x60" crop="center" as im %}
@ -44,11 +47,11 @@
{% endif %} {% endif %}
</div> </div>
<p class="nameMess"> <p class="nameMess">
{% if contact.is_contractor %} {% if contact.is_contractor %}
{% url "users:contractor-profile" pk=contact.pk as contact_url %} {% url "users:contractor-profile" pk=contact.pk as contact_url %}
{% else %} {% else %}
{% url "users:customer-profile-open-projects" pk=contact.pk as contact_url %} {% url "users:customer-profile-open-projects" pk=contact.pk as contact_url %}
{% endif %} {% endif %}
<div><a href="{{ contact_url }}">{{ contact.username }}</a></div> <div><a href="{{ contact_url }}">{{ contact.username }}</a></div>
</p> </p>
@ -69,17 +72,18 @@
<div id="message-chat-space"></div> <div id="message-chat-space"></div>
<form id="contact-chat-form"> <form id="contact-chat-form">
<input type="hidden" value="{{ request.user.pk }}" name="senderId" id="senderContactId"/> <input type="hidden" value="{{ request.user.pk }}" name="senderId" id="senderContactId"/>
<input type="hidden" name="recipentId" id="recipentContactId"> <input type="hidden" name="recipentId" id="recipentContactId">
<textarea id="chat" name="chat_message" class="box-sizing"></textarea> <textarea id="chat" name="chat_message" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p> <p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя
отправить</p>
<div class="bunChat"> <div class="bunChat">
<div class="setChat box-sizing upload"> <div class="setChat box-sizing upload">
<input type="file" name="file" id="upload-document-contact"> <input type="file" name="file" id="upload-document-contact">
<p>Прикрепить файл</p> <p>Прикрепить файл</p>
</div> </div>
<div id="document-send-contact"></div> <div id="document-send-contact"></div>
<a id="contact-chat-add-message" href="#">отправить</a> <a id="contact-chat-add-message" href="#">отправить</a>
</div> </div>
</form> </form>
@ -87,47 +91,51 @@
</div> </div>
<div class="col-lg-3 wrChat1"> <div class="col-lg-3 wrChat1">
<div class="col-lg-12 documentsChat"> <div class="col-lg-12 documentsChat">
<p>Прикрепленные документы</p> <p>Прикрепленные документы</p>
<ul id="documentSpace"> <ul id="documentSpace">
</ul> </ul>
<a href="{% url 'common:create' %}"> <a href="{% url 'common:create' %}">
Распечатать с помощью ресурса Распечатать с помощью ресурса
</a> </a>
</div> </div>
<div class="textAreaBlock2 box-sizing disTab"> <div class="textAreaBlock2 box-sizing disTab">
<p>Заметки</p> <p>Заметки</p>
<ul class="contractor-notes-block"> <ul class="contractor-notes-block">
</ul> </ul>
<form id="add-form-contractor-note"> <form id="add-form-contractor-note">
<p>Для заметок</p> <p>Для заметок</p>
<input type="hidden" name="sender" id="senderNoteContractor" value="{{ request.user.pk }}"/> <input type="hidden" name="sender" id="senderNoteContractor"
<input type="hidden" name="recipent" id="recipentNoteContractor" value=""/> value="{{ request.user.pk }}"/>
<textarea id="chat2" name="text"></textarea> <input type="hidden" name="recipent" id="recipentNoteContractor" value=""/>
<a href="#" id="add-note-contractor">сохранить</a> <textarea id="chat2" name="text"></textarea>
<a href="#" id="add-note-contractor">сохранить</a>
</form> </form>
</div> </div>
</div> </div>
<!-- order-info --> <!-- order-info -->
{% include 'contact-info.html' %} {% include 'contact-info.html' %}
<!-- --> <!-- -->
</div> </div>
<!-- End block Tab1(contacts block)--> <!-- End block Tab1(contacts block)-->
<!-- Tab2 (chat order block)--> <!-- Tab2 (chat order block)-->
<div class="chatBlock disTab tab-pane fade" id="tab2"> <div class="chatBlock disTab tab-pane fade" id="tab2">
<div class="col-lg-3 wrMessages"> <div class="col-lg-3 wrMessages">
<div class="messageBlock box-sizing disTab"> <div class="messageBlock box-sizing disTab">
<p>Заказы</p> <p>Заказы</p>
{% for order in orders %} {% for order in orders %}
<div class="orderBlock box-sizing order-block" data-project-id="{{ order.id }}" <div class="orderBlock box-sizing order-block"
id="orderBlock{{ order.order.id }}" data-secure-deal="{% if order.order.secure %}true{% else %}false{% endif %}" data-team-id="{% if order.order.team %}{{ order.order.team.pk }}{% else %}0{% endif %}"
{% if order.order.contractor %} data-project-id="{{ order.id }}"
id="orderBlock{{ order.order.id }}"
data-secure-deal="{% if order.order.secure %}true{% else %}false{% endif %}"
{% if order.order.contractor %}
data-recipent-id="{{ order.order.contractor.pk }}" data-recipent-id="{{ order.order.contractor.pk }}"
{% else %} {% else %}
data-recipent-id="{{ order.order.team.owner.pk }}" data-recipent-id="{{ order.order.team.owner.pk }}"
{% endif %} data-id="{{ order.order.id }}"> {% endif %} data-id="{{ order.order.id }}">
<span class="dimovChat"></span> <span class="dimovChat"></span>
<p class="titleOB">{{ order }}</p> <p class="titleOB">{{ order }}</p>
<div class="hideOBB"> <div class="hideOBB">
@ -144,21 +152,47 @@
Полное описание заказа Полное описание заказа
</a> </a>
<a href="#" class="deleteOrder" data-project-id="{{ order.pk }}"> <a href="#" class="deleteOrder" data-project-id="{{ order.pk }}">
Удалить заказ Удалить заказ
</a> </a>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
<div class="textAreaBlock2 FFD box-sizing disTab">
<a href="#" data-show="true" id="trashed-button">Показать архивные заказы</a>
</div>
<p id="show-archive-label">Архивные заказы</p>
<div id="trashed-orders"></div>
</div> {% if archive_projects %}
<div class="textAreaBlock2 FFD box-sizing disTab">
<a href="#" data-show="true" id="trashed-button">Показать архивные заказы</a>
</div>
<p id="show-archive-label" style="display: none;">Архивные заказы</p>
<div id="archive-space" style="display:none;">
<div id="trashed-orders">
{% for proj in archive_projects %}
<div data-id="{{ proj.order.id }}" class="trashedOrderBlock box-sizing">
<span class="dimovChat"></span>
<p class="titleOB"> {{ proj.name }}</p>
<div class="hideOBB"><p class="pOB">
<span>Исполнитель:
{% if proj.order.contractor %}
{{ proj.order.contractor.get_full_name }}
{% else %}
{{ proj.order.team.name }}
{% endif %}
</span>
</p>
<a href="#" class="linkChat11 full-order-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Полное описание заказа
</a>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div> </div>
<div class="col-lg-6 commChat"> <div class="col-lg-6 commChat">
<div id="message-chat-order-space"></div> <div id="message-chat-order-space"></div>
@ -167,11 +201,12 @@
<input type="hidden" name="recipentId" id="recipentId"> <input type="hidden" name="recipentId" id="recipentId">
<input type="hidden" name="orderId" id="orderId"> <input type="hidden" name="orderId" id="orderId">
<textarea id="chat" class="box-sizing"></textarea> <textarea id="chat" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p> <p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя
отправить</p>
<div class="bunChat"> <div class="bunChat">
<div class="setChat box-sizing upload"> <div class="setChat box-sizing upload">
<input type="file" name="file" id="upload-document-order"> <input type="file" name="file" id="upload-document-order">
<p>Прикрепить файл</p> <p>Прикрепить файл</p>
</div> </div>
<div id="document-send-order"></div> <div id="document-send-order"></div>
<a href="#" id="order-chat-add-message">отправить</a> <a href="#" id="order-chat-add-message">отправить</a>
@ -198,44 +233,44 @@
<ul class="stages-paid"></ul> <ul class="stages-paid"></ul>
<div class="textAreaBlock2 FFD box-sizing disTab"> <div class="textAreaBlock2 FFD box-sizing disTab">
<a href="#" id="reserve-button" data-order-id="">Зарезервировать</a> <a href="#" id="reserve-button" data-order-id="">Зарезервировать</a>
</div> </div>
</div> </div>
<!-- Зарезервировать средства (модальное окно)--> <!-- Зарезервировать средства (модальное окно)-->
{% include 'reverse_stage_modal.html' %} {% include 'reverse_stage_modal.html' %}
<!-- Конец блока --> <!-- Конец блока -->
<div class="stepssBlock box-sizing disTab" id="completeWork"> <div class="stepssBlock box-sizing disTab" id="completeWork">
<p class="titleStepss">3 / Выполнение работы</p> <p class="titleStepss">3 / Выполнение работы</p>
<p class="textStepss"> <p class="textStepss">
Процесс выполнения задания в заказе до получения Процесс выполнения задания в заказе до получения
заказчиком итогового результата работы. заказчиком итогового результата работы.
</p> </p>
<div id="stagesWork" class="stages-work"></div> <div id="stagesWork" class="stages-work"></div>
</div> </div>
<div id="leaveReview" style="display: none;"> <div id="leaveReview" style="display: none;">
<div class="closeChat closeChat1"> <div class="closeChat closeChat1">
<a href="#" data-toggle="modal" data-target="#review-add" data-review-type="positive"> <a href="#" data-toggle="modal" data-target="#review-add" data-review-type="positive">
Закрыть проект<br>и оставить отзыв Закрыть проект<br>и оставить отзыв
</a> </a>
</div> </div>
<div class="closeChat closeChat2"> <div class="closeChat closeChat2">
<a href="#" data-toggle="modal" data-target="#review-add" data-review-type="negative"> <a href="#" data-toggle="modal" data-target="#review-add" data-review-type="negative">
Закрыть проект<br>и оставить отзыв Закрыть проект<br>и оставить отзыв
</a> </a>
</div> </div>
</div> </div>
<div class="col-lg-12 documentsChat"> <div class="col-lg-12 documentsChat">
<p>Прикрепленные документы</p> <p>Прикрепленные документы</p>
<ul id="documentOrderSpace"></ul> <ul id="documentOrderSpace"></ul>
<a href="{% url 'common:create' %}"> <a href="{% url 'common:create' %}">
Распечатать с помощью ресурса Распечатать с помощью ресурса
</a> </a>
</div> </div>
<div class="textAreaBlock2 box-sizing disTab"> <div class="textAreaBlock2 box-sizing disTab">
<ul class="order-notes-block"> <ul class="order-notes-block">
@ -265,7 +300,7 @@
</div> </div>
</div> </div>
<!-- End block (chat order block) --> <!-- End block (chat order block) -->
</div> </div>
{% include 'partials/footer.html' %} {% include 'partials/footer.html' %}
</div> </div>
@ -275,11 +310,11 @@
{% block js_block %} {% block js_block %}
<script type="text/javascript"> <script type="text/javascript">
var userId = {{ request.user.pk }}; var userId = {{ request.user.pk }};
var domain = '{{ request.META.HTTP_HOST }}'; var domain = '{{ request.META.HTTP_HOST }}';
var port = '{{ request.META.SERVER_PORT }}'; var port = '{{ request.META.SERVER_PORT }}';
</script> </script>
<script type="text/javascript" src='{% static "js/chat.js" %}'></script> <script type="text/javascript" src='{% static "js/chat.js" %}'></script>
<script type="text/javascript" src='{% static "js/chat_customer.js" %}'></script> <script type="text/javascript" src='{% static "js/chat_customer.js" %}'></script>
{% endblock %} {% endblock %}

@ -37,7 +37,7 @@
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<select class="selectpicker -project-work-type-select-field" id="stagesSelect"> <select id="stagesSelect">
</select> </select>
</div> </div>
</div> </div>

@ -13,13 +13,13 @@
<div style="height: 250px;"> <div style="height: 250px;">
{# <div class="searchF1 polsF1 polsFF radio-afer">#} {# <div class="searchF1 polsF1 polsFF radio-afer">#}
<div> <div>
<input type="radio" value="positive" <input style="opacity: 1;" type="radio" value="positive"
name="type">Положительный name="type">Положительный
<input type="radio" value="negative" <input style="opacity: 1;" type="radio" value="negative"
name="type">Отрицательный name="type">Отрицательный
<input type="radio" value="neutral" <input style="opacity: 1;" type="radio" value="neutral"
name="type">Нейтральный name="type">Нейтральный
</div> </div>
@ -27,19 +27,19 @@
<p>Ваш отзыв</p> <p>Ваш отзыв</p>
<textarea id="text-new" name="text"></textarea> <textarea id="text-new" name="text"></textarea>
{% if request.user.is_customer %} {% if request.user.is_customer %}
<input type="hidden" name="from_customer" value="{{ request.user.pk }}"/> <input type="hidden" name="from_customer" value="{{ request.user.pk }}">
<input type="hidden" name="from_contractor"> <input type="hidden" name="from_contractor">
<input type="hidden" name="from_team"> <input type="hidden" name="from_team">
<input type="hidden" name="target_contractor" id="targetContractorId"/> <input type="hidden" name="target_contractor" id="targetContractorId">
<input type="hidden" name="target_customer"> <input type="hidden" name="target_customer">
<input type="hidden" name="target_team"> <input type="hidden" name="target_team" id="targetTeamId">
{% else %} {% else %}
<input type="hidden" name="from_customer"/> <input type="hidden" name="from_customer">
<input type="hidden" name="from_contractor" value="{{ request.user.pk }}"> <input type="hidden" name="from_contractor" id="fromContractorId">
<input type="hidden" name="target_customer" id="targetCustomerId"> <input type="hidden" name="target_customer" id="targetCustomerId">
<input type="hidden" name="target_contractor"> <input type="hidden" name="target_contractor">
<input type="hidden" name="target_team"> <input type="hidden" name="target_team">
<input type="hidden" name="from_team"> <input type="hidden" name="from_team" id="fromTeamId">
{% endif %} {% endif %}
<input type="hidden" name="project" id="projectReviewId"/> <input type="hidden" name="project" id="projectReviewId"/>
</div> </div>

@ -55,7 +55,7 @@ class ChatUserView(LoginRequiredMixin, View):
users_ids.append(int(user_id)) users_ids.append(int(user_id))
contacts_users = User.objects.filter(pk__in=users_ids) contacts_users = User.objects.filter(pk__in=users_ids)
archive_projects = request.user.customer_projects.select_related('order').exclude(state='active')
chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)) chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk))
orders = request.user.customer_projects.select_related('order').filter(state='active').exclude(order__contractor__isnull=True, order__team__isnull=True) orders = request.user.customer_projects.select_related('order').filter(state='active').exclude(order__contractor__isnull=True, order__team__isnull=True)
order_ids = [order.order.pk for order in orders] order_ids = [order.order.pk for order in orders]
@ -72,6 +72,7 @@ class ChatUserView(LoginRequiredMixin, View):
'chat_messages': chat_messages, 'chat_messages': chat_messages,
'contacts_users_count': contacts_users_count, 'contacts_users_count': contacts_users_count,
'orders_ms_count': orders_ms_count, 'orders_ms_count': orders_ms_count,
'archive_projects': archive_projects,
'orders': orders, 'orders': orders,
'transaction': transaction[0], 'transaction': transaction[0],
'YANDEX_MONEY': settings.YANDEX_MONEY, 'YANDEX_MONEY': settings.YANDEX_MONEY,
@ -86,7 +87,8 @@ class ChatUserView(LoginRequiredMixin, View):
teams = Team.objects.filter(contractors__id=request.user.pk).all() 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() team_orders = Order.objects.filter(team_id__in=[team.pk for team in teams]).all()
orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).filter(project__state='active').all() orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).filter(project__state='active')
archive_orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).exclude(project__state='active')
contractor_contacts = Message.objects.values_list('sender_id', 'recipent_id').filter( contractor_contacts = Message.objects.values_list('sender_id', 'recipent_id').filter(
Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)).\ Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)).\
filter(is_delete=False).distinct() filter(is_delete=False).distinct()
@ -113,7 +115,6 @@ class ChatUserView(LoginRequiredMixin, View):
orders_ms_count = request.user.new_messages.filter(message__order__in=orders, message__team__isnull=True).count() orders_ms_count = request.user.new_messages.filter(message__order__in=orders, message__team__isnull=True).count()
teams_ms_count = request.user.new_messages.filter(message__team__in=your_teams, message__order__isnull=True).count() teams_ms_count = request.user.new_messages.filter(message__team__in=your_teams, message__order__isnull=True).count()
self.template_name = 'chat_contractor.html' self.template_name = 'chat_contractor.html'
return render(request, self.template_name, {'orders': orders, return render(request, self.template_name, {'orders': orders,
'contacts_users': contacts_users, 'contacts_users': contacts_users,
@ -123,7 +124,7 @@ class ChatUserView(LoginRequiredMixin, View):
'chat_messages': chat_messages, 'chat_messages': chat_messages,
'team_orders': team_orders, 'team_orders': team_orders,
'your_teams': your_teams, 'your_teams': your_teams,
'archive_orders': archive_orders,
}) })

@ -1,15 +1,18 @@
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import Review from .models import Review
from users.serializers import UserSerializer, TeamSerializer from users.serializers import UserSerializer, TeamSerializer
class ReviewSerializer(ModelSerializer): class ReviewSerializer(ModelSerializer):
target_user = serializers.SerializerMethodField(read_only=True)
class Meta: class Meta:
model = Review model = Review
fields = ( fields = (
'id',
'text', 'text',
'type', 'type',
'created', 'created',
@ -20,5 +23,14 @@ class ReviewSerializer(ModelSerializer):
'target_customer', 'target_customer',
'target_contractor', 'target_contractor',
'target_team', 'target_team',
'target_user',
) )
def get_target_user(self, obj):
if obj.target_customer:
return obj.target_customer.pk
elif obj.target_contractor:
return obj.target_contractor.pk
elif obj.target_team:
return obj.target_team.owner.pk

@ -68,3 +68,18 @@ def get_new_count_for_contact(contact, current_user):
return count return count
@register.simple_tag
def get_new_count_for_order(current_user, order_id):
count = current_user.new_messages.filter(message__order=order_id, message__team__isnull=True).count()
return count
@register.simple_tag
def get_new_count_for_team(current_user, team_id, order_id=None):
if order_id:
count = current_user.new_messages.filter(message__order=order_id, message__team=team_id).count()
else:
count = current_user.new_messages.filter(message__order__isnull=True, message__team=team_id).count()
return count

Loading…
Cancel
Save