diff --git a/archilance/views.py b/archilance/views.py index 0532bba..a51e9aa 100644 --- a/archilance/views.py +++ b/archilance/views.py @@ -7,9 +7,11 @@ from django.http import HttpResponseForbidden, JsonResponse, HttpResponseRedirec from django.shortcuts import render, get_object_or_404, redirect from django.views.generic import TemplateView, View from pprint import pprint, pformat +import json import logging from .mixins import BaseMixin +from archilance import util from chat.models import Documents from common.models import MainPage, PrintDocuments from projects.models import Order @@ -52,8 +54,22 @@ class TestView(BaseMixin, View): def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) + data = {} - context['foo'] = 'bar' + from projects.models import Project + from projects.serializers import ProjectSerializer + from users.models import User + from users.serializers import UserSerializer + contractor = User.contractor_objects.get(pk=11) + project = Project.objects.get(pk=153) + + data['contractor'] = UserSerializer(contractor).data + data['project'] = ProjectSerializer(project).data + + context['data_json'] = json.dumps(data) return render(request, self.template_name, context) # return redirect('projects:detail', pk=153) + + +# import code; code.interact(local=dict(globals(), **locals())) diff --git a/assets/index.js b/assets/index.js index 1aea79f..4a2cdc1 100644 --- a/assets/index.js +++ b/assets/index.js @@ -239,7 +239,7 @@ var projectSelectOptions = { } function initProjectSelect($select, customerId) { - return $.ajax({url: '/api/projects/?customer=' + customerId, method: 'GET', dataType: 'json'}) + return $.ajax({url: '/api/projects/?state=active&customer=' + customerId, method: 'GET', dataType: 'json'}) .then(function(res) { var projects = res.results diff --git a/assets/js/chat.js b/assets/js/chat.js index 744d209..a7bf879 100644 --- a/assets/js/chat.js +++ b/assets/js/chat.js @@ -1,6 +1,6 @@ var SocketHandler = function () { domain = domain.replace(':' + port, ''); - var url = 'ws://' + domain + '/chat/' + userId + '/'; + var url = 'ws://' + domain + ':8888/chat/' + userId + '/'; var sock = new WebSocket(url); var intervalId; sock.onopen = function () { diff --git a/common/mixins.py b/common/mixins.py index 3d4fd79..f3b0433 100644 --- a/common/mixins.py +++ b/common/mixins.py @@ -1,3 +1,5 @@ +from django.contrib.auth.mixins import LoginRequiredMixin +from django.core.exceptions import PermissionDenied from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views.generic import View @@ -7,3 +9,19 @@ class NoCsrfMixin(View): @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) + + +class CustomerRequiredMixin(LoginRequiredMixin, View): + def dispatch(self, request, *args, **kwargs): + if request.user.is_customer(): + return super().dispatch(request, *args, **kwargs) + else: + raise PermissionDenied + + +class ContractorRequiredMixin(LoginRequiredMixin, View): + def dispatch(self, request, *args, **kwargs): + if request.user.is_contractor(): + return super().dispatch(request, *args, **kwargs) + else: + raise PermissionDenied diff --git a/common/templatetags/common_tags.py b/common/templatetags/common_tags.py index 93addd9..cb22262 100644 --- a/common/templatetags/common_tags.py +++ b/common/templatetags/common_tags.py @@ -61,6 +61,11 @@ def to_list(val): return list(val) +@register.filter('repr') +def to_repr(val): + return repr(val) + + @register.filter def class_name(val): return type(val).__name__ diff --git a/projects/serializers.py b/projects/serializers.py index 4984c64..07658ad 100755 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -71,11 +71,34 @@ class StageSerializer(ModelSerializer): ) +class OrderSerializer_(ModelSerializer): + contractor = UserSerializer() + stages = StageSerializer(many=True) + team = TeamSerializer() + project_id = PrimaryKeyRelatedField(read_only=True, source='project') + + class Meta: + model = Order + + fields = ( + 'created', + 'id', + 'secure', + 'status', + + 'contractor', + 'project_id', + 'stages', + 'team', + ) + + class ProjectSerializer(ModelSerializer): customer = UserSerializer() specialization = SpecializationSerializer() realty = RealtySerializer() - + order = OrderSerializer_() # TODO: Can't serialize a reverse/reciprocal relation + class Meta: model = Project @@ -89,6 +112,7 @@ class ProjectSerializer(ModelSerializer): 'deal_type', 'id', 'name', + 'order', 'price_and_term_required', 'realty', 'specialization', @@ -97,7 +121,6 @@ class ProjectSerializer(ModelSerializer): 'term_type', 'text', 'work_type', - ) diff --git a/projects/templates/comparison.html b/projects/templates/comparison.html index eef4d49..31b097a 100644 --- a/projects/templates/comparison.html +++ b/projects/templates/comparison.html @@ -9,8 +9,7 @@
-

- Сравнение кандидатов по проекту

+

Сравнение кандидатов по проекту

@@ -18,92 +17,95 @@

{{ object }}

- - - - - - - - - - + + + + + + + + + + + - {% for cand in object.candidates.all %} - - - - - - - - - - - - + + + + + + + + + + + + + - - - - + + - - {% endfor %} + + + {% csrf_token %} + + + + +
+
+ + + + {% endfor %}
КандидатЦенаСрокОписаниеРейтинги/отзывыБезопасные сделкиРешение
КандидатЦенаСрокОписаниеРейтинги/отзывыБезопасные сделкиРешение
{{ cand.position }} - {% if cand.answer.author|class_name == 'User' %} - {{ cand.answer.author.get_full_name }} - {% elif cand.answer.author|class_name == 'Team' %} - {{ cand.answer.author.name }} - {% endif %} - {{ cand.answer.budget }} - {% if cand.answer.term_type == 'project' %} - За проект - {% else %} - {% morph cand.answer.term TERM_TYPE_MORPHS|get:cand.answer.term_type %} - {% endif %} - - - -
    - -
  • {{ cand.answer.author.rating }}
  • - -
  • - +0 0 - 0 -
  • - - {% if cand.answer.author.cro %} + {% for cand in object.candidates.all %} +
{{ cand.position }} + {% if cand.answer.author|class_name == 'User' %} + {{ cand.answer.author.get_full_name }} + {% elif cand.answer.author|class_name == 'Team' %} + {{ cand.answer.author.name }} + {% endif %} + {{ cand.answer.budget }} + {% if cand.answer.term_type == 'project' %} + За проект + {% else %} + {% morph cand.answer.term TERM_TYPE_MORPHS|get:cand.answer.term_type %} + {% endif %} + + + +
    + +
  • {{ cand.answer.author.rating }}
  • +
  • - СРО + +0 0 - 0
  • + + {% if cand.answer.author.cro %} +
  • + СРО +
  • + {% endif %} +
+
+ 0
+ {% if cand.answer.secure_deal_only %} + Готов работать по безопасной сделке {% endif %} - -
- 0
- {% if cand.answer.secure_deal_only %} - Готов работать по безопасной сделке - {% endif %} -
-
-
- {% csrf_token %} - -
+
+
+ + {% csrf_token %} + + +
+
+ + + +
- - - -
-
- -
- {% csrf_token %} -
- - -
-
-
-
@@ -112,8 +114,9 @@
{% endblock %} + {% block js_block %} -
-{# {% url 'projects:customer-offer-order-answerless' contractor_id=11 project_id=485 as url %}#} -{# #} -{#
#} -{# {% csrf_token %}#} -{# #} -{# #} -{#
#} +
{{ data_json }}
diff --git a/users/templates/contractor_filter.html b/users/templates/contractor_filter.html index e209bbe..c3e4afe 100644 --- a/users/templates/contractor_filter.html +++ b/users/templates/contractor_filter.html @@ -173,7 +173,7 @@ {% with team=obj %}
- +
{% if team.owner.avatar %} {% thumbnail team.owner.avatar "126x125" crop="center" as avatar %} @@ -185,7 +185,7 @@

- {{ team.name }} {# TODO #} + {{ team.name }}

Свободен
@@ -201,15 +201,20 @@
  • {% if request.user.is_customer %} - - предложить проект + + предложить проект {% endif %}
  • -{# TODO #} -{# #} - + написать сообщение
  • @@ -223,17 +228,9 @@
    - + {% ratings_team_widget team.pk 'restList2' %} + +

    Есть допуск СРО

    @@ -329,7 +326,6 @@ @@ -354,11 +350,12 @@
    {% ratings_widget contractor.pk 'restList2' %} + {% if contractor.cro %} -
    -
    -

    Есть допуск СРО

    -
    +
    +
    +

    Есть допуск СРО

    +
    {% endif %}
    @@ -415,6 +412,9 @@ {% if request.user.is_customer %} var customerId = {{ request.user.pk }} var $projectSelectionModal = $('#projectSelectionModal') + var projectUrl_ = '/projects/%id%/' + var projectOrderChatUrl_ = '/chat/#order%orderId%' + $projectSelectionModal.on('shown.bs.modal', function($evt) { var $that = $(this) @@ -427,33 +427,66 @@ initProjectSelect($projectSelect, customerId) }) + $projectSelectionModal.find('.-action-button').first().on('click', function($evt) { var $projectSelect = $projectSelectionModal.find('.-project-select').first() var $modalOpenButton = $projectSelectionModal.data('modalOpenButton') var isTeamOffer = $modalOpenButton.data('isTeamOffer') - var project = $projectSelect.select2('data') - var contractorId = $modalOpenButton.data('contractorId') + var project = $projectSelect.select2('data').origItem + var projectUrl = _.replace('%id%', project.id, projectUrl_) + var projectOrderChatUrl = _.replace('%orderId%', project.order.id, projectOrderChatUrl_) $projectSelectionModal.modal('hide') - $projectSelect.select2('destroy') - - if (isTeamOffer) - var msg = 'Вашей команде предлагается проект ' + project.id - else - var msg = 'Вам предлагается проект ' + project.id - socketMain.add_message({ - format_type: 'add_message_contact', + if (isTeamOffer) { + var contractorId = $modalOpenButton.data('contractorId') + var teamId = $modalOpenButton.data('teamId') - data: { - sender_id: customerId, - recipent_id: contractorId, - chat_message: msg, - }, - }) - - $.jGrowl('Предложение успешно отправлено') - $modalOpenButton.fadeOut() + if (project.order.team && project.order.team.id === teamId) { + window.location.href = projectOrderChatUrl + } else { + var msg = 'Вашей команде предлагается проект http://{{ request.get_host }}' + projectUrl + + socketMain.add_message({ + format_type: 'add_message_contact', + + data: { + sender_id: customerId, + recipent_id: contractorId, + chat_message: msg, + }, + }) + } + + $.jGrowl('Предложение успешно отправлено') + $modalOpenButton.fadeOut() + } else { + var contractorId = $modalOpenButton.data('contractorId') + + if (project.order.contractor && project.order.contractor.id === contractorId) { + window.location.href = projectOrderChatUrl + } else { + var msg = 'Вам предлагается проект http://{{ request.get_host }}' + projectUrl + + socketMain.add_message({ + format_type: 'add_message_contact', + + data: { + sender_id: customerId, + recipent_id: contractorId, + chat_message: msg, + }, + }) + } + + $.jGrowl('Предложение успешно отправлено') + $modalOpenButton.fadeOut() + } + }) + + + $projectSelectionModal.on('hidden.bs.modal', function($evt) { + $(this).find('.-project-select').first().select2('destroy') }) {% endif %} diff --git a/users/templates/contractor_profile.html b/users/templates/contractor_profile.html index dccfae9..5a9a704 100644 --- a/users/templates/contractor_profile.html +++ b/users/templates/contractor_profile.html @@ -4,6 +4,7 @@ {% load thumbnail %} {% block content %} + {% include 'partials/modals/project_selection.html' %} {% include 'partials/header.html' %}
    + + +
    {{ contractor.contractor_resume.text|safe }}
    - - - + {% endif %}
    -
    -
    -
    -

    {{ object.budget }}

    -
    - {% if request.user.is_authenticated %} + + {% if object.contractor %} + + {% endif %}