#ARC-16 Fixes chat

remotes/origin/PR-39
Mukhtar 9 years ago
parent c7eb3c3ba3
commit e4846f39da
  1. 51
      assets/css/extra.css
  2. 47
      assets/js/chat.js
  3. 51
      assets/js/chat_customer.js
  4. 12
      chat/chat.py
  5. 2
      chat/serializers.py
  6. 11
      chat/templates/chat_contractor.html
  7. 10
      chat/templates/chat_customer.html
  8. 2
      chat/views.py
  9. 20
      projects/migrations/0037_auto_20160919_1126.py
  10. 20
      ratings/migrations/0002_historyrating_type.py
  11. 10
      ratings/models.py
  12. 3
      users/models.py
  13. 7
      users/templatetags/user_tags.py

@ -189,3 +189,54 @@
font-style: italic;
}
.trashedOrderBlock {
width: 100%;
float: left;
margin-bottom: -1px;
padding: 15px;
background-color: #F7F7F7;
border-top: 1px solid #72767C;
border-bottom: 1px solid #72767C;
position: relative;
cursor: pointer;
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.trashedOrderBlock:hover {
background-color: white;
border-top: 1px solid black;
border-bottom: 1px solid black;
-webkit-transform: scale(1.03);
-moz- transform: scale(1.03);
transform: scale(1.03);
box-shadow: 0 0 10px rgba(0,0,0,0.7);
z-index: 999;
}
.count-tab{
margin-left: 10px;
width: 35px;
height: 35px;
border-radius: 100%;
line-height: 35px;
text-align: center;
font-size: 14px;
font-family: 'Arial-MT-Regular', sans-serif;
position: absolute;
top: 14px;
cursor: pointer;
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
background-color: #ebebeb;
}
li a:active .count-tab, li a:hover .count-tab{
background-color: #FF0027;
color: white;
}

@ -64,7 +64,7 @@ var SocketHandler = function () {
} else if (message.answer_type == 'approve_stages') {
var resOrderId = message.order_id;
$.jGrowl(message.msg, {
life: 4000
life: 15000
});
setTimeout(function () {
$("#orderBlock" + resOrderId).trigger('click');
@ -185,51 +185,6 @@ function dialog (message, yesCallback, notCallback) {
}
$(".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();
});
// Информация о заказе
$(".messageBlock").on('click','.full-order-info', function (e) {
e.preventDefault();

@ -137,7 +137,7 @@ $(function () {
'<p>Этап</p><form class="update-stages-form" data-stage-id="' + v.id + '" id="stage-form-' + v.pos + '">' +
'<label>Название</label><input class="form-control" type="text" name="name" value="' + v.name + '"><p class="error error-name"></p>' +
'<label>Цена</label><input class="form-control" type="text" name="cost" value="' + v.cost + '" ><p class="error error-cost"></p>' +
'<label>Позиция</label><input class="form-control" name="pos" type="text" value="' + v.pos + '" ><p class="error error-pos"></p>' +
'<input class="form-control" name="pos" type="hidden" value="' + v.pos + '" ><p class="error error-pos"></p>' +
'<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '">' +
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<label>Срок</label><input class="term-picker form-control datepicker" type="text" name="term" value="' + v.term + '" ><p class="error error-term"></p>' +
@ -366,6 +366,7 @@ $(function () {
"msg": "Этапы для заказа " + currentOrderId + " изменены",
}
});
$.jGrowl("Этапы для заказа изменены и отправлены исполнителю", { life: 15000});
});
@ -390,7 +391,7 @@ $(function () {
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<label>Срок</label><input class="term-picker form-control datepicker" name="term" type="text"><p class="error error-term"></p>' +
'<label>Результат</label><input class="form-control" name="result" type="text"><p class="error error-result"></p>' +
'<input class="form-control" name="pos" value="' + pos + '" type="text"></form></div>';
'<input class="form-control" name="pos" value="' + pos + '" type="hidden"></form></div>';
lastFormStage.after(addFormTemplate);
}
@ -408,7 +409,7 @@ $(function () {
}
});
// Нажимаем на кнопку архивные сообщения
$("#trashed-button").on('click',function(e){
e.preventDefault();
var state = $(this).attr('data-show');
@ -452,6 +453,50 @@ $(function () {
});
// Нажимаем на заказ в архмвных заказах
$(".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 () {

@ -24,12 +24,13 @@ class ChatHandler(websocket.WebSocketHandler):
waiters = set()
def open(self, *args, **kwargs):
self.user_id = kwargs.get('user_id',1)
self.user_id = kwargs.get('user_id', 1)
self.waiters.add((self.user_id, self))
# @gen.coroutine
def on_message(self, message):
parsed = escape.json_decode(message)
if 'dummy' in parsed:
return
@ -50,9 +51,10 @@ class ChatHandler(websocket.WebSocketHandler):
# order_id = data['data'].get('order_id')
# message = data['data'].get('msg', 'Этапы обновлены')
# answer_type = data['format_type']
# waiters = tuple(w for c, w in self.waiters if c == recipent_id or c == sender_id)
# waiters = tuple(w for c, w in self.waiters if c == recipent_id)
# for waiter in waiters:
# waiter.write_message({'msg': message, 'order_id': order_id, 'answer_type': answer_type})
# print(waiter)
# # waiter.write_message({'msg': message, 'order_id': order_id, 'answer_type': answer_type})
@gen.coroutine
def add_message(self, message_data):
@ -127,7 +129,11 @@ class ChatHandler(websocket.WebSocketHandler):
if docs_links:
message += '<br><br>' + docs_links;
if message_type:
waiters = tuple(w for c, w in self.waiters if c == recipent_id)
else:
waiters = tuple(w for c, w in self.waiters if c == recipent_id or c == sender_id)
for waiter in waiters:
waiter.write_message({'msg': message,
'msg_time': msg_time,

@ -63,7 +63,7 @@ class MessageSerializer(ModelSerializer):
out = obj.text
documents = obj.documents.all()
if len(documents)>0:
documents_str = '<br>'.join(['Входящий файл: <br><a target="_blank" href="/chat/download/' + doc.file.name + '">' + doc.file.name + '</a>' for doc in documents])
documents_str = '<br>'.join(['Приложенный файл: <br><a target="_blank" href="/chat/download/' + doc.file.name + '">' + doc.file.name + '</a>' for doc in documents])
out += '<br><br>' + documents_str
return out

@ -1,6 +1,7 @@
{% extends 'partials/base.html' %}
{% load staticfiles %}
{% load thumbnail %}
{% load user_tags %}
{% block content %}
{% include 'partials/header.html' %}
<div class="container mainScore">
@ -16,15 +17,15 @@
<ul class="nav nav-tabs nav-justified">
<li role="presentation">
<a href="#tab1" data-toggle="tab">Личные</a>
<a href="#tab1" data-toggle="tab">Личные<span class="count-tab">0</span></a>
</li>
<li role="presentation">
<a href="#tab2" data-toggle="tab">Заказчики</a>
<a href="#tab2" data-toggle="tab">Заказчики<span class="count-tab">0</span></a>
</li>
<li role="presentation">
<a href="#tab3" data-toggle="tab">Исполнители,Группы</a>
<a href="#tab3" data-toggle="tab">Исполнители,Группы<span class="count-tab">0</span></a>
</li>
</ul>
@ -56,8 +57,8 @@
</p>
<a href="#" data-id="{{ contact.id }}" class="conMess">Контакты</a>
<span class="contact-count-{{ contact.pk|add:request.user.pk }}">0</span>
<span class="contact-count-{{ contact.pk|add:request.user.pk }}">
{% get_new_count_for_contact contact request.user %}</span>
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт
</a>

@ -1,6 +1,7 @@
{% extends 'partials/base.html' %}
{% load staticfiles %}
{% load thumbnail %}
{% load user_tags %}
{% block content %}
{% include 'partials/header.html' %}
<div class="container mainScore">
@ -14,10 +15,11 @@
<div class="profileTabs2">
<ul class="nav nav-tabs nav-justified">
<li role="presentation">
<a href="#tab1" data-toggle="tab">Личные</a>
<a href="#tab1" data-toggle="tab">Личные<span class="count-tab">0</span></a>
</li>
<li role="presentation">
<a href="#tab2" data-toggle="tab">Исполнители</a>
<a href="#tab2" data-toggle="tab">Исполнители<span class="count-tab">0</span>
</a>
</li>
</ul>
</div>
@ -52,7 +54,9 @@
<a href="#" data-id="{{ contact.id }}" class="conMess">Контакты</a>
<span class="contact-count-{{ contact.pk|add:request.user.pk }}">0</span>
<span class="contact-count-{{ contact.pk|add:request.user.pk }}">
{% get_new_count_for_contact contact request.user %}
</span>
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт
</a>

@ -53,12 +53,14 @@ class ChatUserView(LoginRequiredMixin, View):
users_ids.append(b)
if user_id:
users_ids.append(int(user_id))
print(users_ids)
contacts_users = User.objects.filter(pk__in=users_ids)
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)
transaction = Transaction.objects.get_or_create(customer=request.user, type='reservation', complete=False)
self.template_name = 'chat_customer.html'
return render(request, self.template_name, {'contacts_users': contacts_users,
'chat_messages': chat_messages,
'orders': orders,

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-19 08:26
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0036_auto_20160917_2135'),
]
operations = [
migrations.AlterField(
model_name='project',
name='work_type',
field=models.IntegerField(choices=[(1, 'Проектирование'), (2, 'Проверка документации'), (3, 'Устранение замечаний в проекте')], default=1),
),
]

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-19 08:26
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ratings', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='historyrating',
name='type',
field=models.CharField(choices=[('OCCUPANCY_PROFILE', 'occupancy_profile'), ('SECURE_DEAL', 'secure_deal'), ('REVIEW', 'review'), ('MONEY_SPENT', 'money_spent'), ('PUBLICATION_PROJECT', 'publication_project'), ('VISIT_SITE', 'visit_site'), ('CHOICE_CONTRACTOR', 'choice_contractor')], default='review', max_length=50),
),
]

@ -5,11 +5,21 @@ from specializations.models import Specialization
class HistoryRating(models.Model):
TYPES_HISTORY_RATING = (
('OCCUPANCY_PROFILE', 'occupancy_profile'),
('SECURE_DEAL', 'secure_deal'),
('REVIEW', 'review'),
('MONEY_SPENT', 'money_spent'),
('PUBLICATION_PROJECT', 'publication_project'),
('VISIT_SITE', 'visit_site'),
('CHOICE_CONTRACTOR', 'choice_contractor'),
)
user = models.ForeignKey(User, related_name='history_ratings', null=True, blank=True)
team = models.ForeignKey(Team, related_name='history_ratings', null=True, blank=True)
rating = models.IntegerField(default=0)
created = models.DateTimeField(default=timezone.now)
description = models.TextField(blank=True)
type = models.CharField(max_length=50, choices=TYPES_HISTORY_RATING, default='review')
def __str__(self):
return '{0}'.format(self.rating)

@ -171,7 +171,8 @@ class User(AbstractBaseUser, PermissionsMixin):
return self.email
def get_full_name(self):
return self.first_name + ' ' + self.last_name
full_name = self.first_name + ' ' + self.last_name
return full_name or self.username
def get_profile_image(self):
return self.avatar

@ -60,3 +60,10 @@ def count_new_message_orders(context, user):
def get_new_count_message(team_pk,user=None):
count = NewMessage.objects.filter(user=user, message__team=team_pk, message__order__isnull=True).count()
return count
@register.simple_tag
def get_new_count_for_contact(contact, current_user):
count = current_user.new_messages.filter(message__sender=contact).count()
return count

Loading…
Cancel
Save