remotes/origin/PR-39
ArturBaybulatov 10 years ago
commit 3ed593b96c
  1. 19
      projects/migrations/0005_auto_20160812_1931.py
  2. 3
      projects/models.py
  3. 129
      projects/templates/comparison.html
  4. 2
      projects/urls.py
  5. 51
      projects/views.py
  6. 3
      users/templates/contractor_profile.html
  7. 5
      work_sell/templates/worksell_edit.html

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-12 16:31
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('projects', '0004_merge'),
]
operations = [
migrations.AlterModelOptions(
name='candidate',
options={'ordering': ('position',), 'verbose_name': 'Кандидат', 'verbose_name_plural': 'Кандидаты'},
),
]

@ -206,9 +206,10 @@ class Candidate(models.Model):
position = models.PositiveIntegerField(default=0)
def __str__(self):
return self.answer.user.get_full_name()
return str(self.answer.pk)
class Meta:
ordering = ('position',)
verbose_name = 'Кандидат'
verbose_name_plural = 'Кандидаты'

@ -4,44 +4,47 @@
{% block content %}
{% include 'partials/header.html' %}
<div class="container mainScore">
<div class="row">
<div class="col-lg-12">
<p class="titleScore">Сравнение кандидатов по проекту</p>
</div>
<div class="titleBlockComparison disTab">
<div class="triangle1"></div>
<p>{{ object }}</p>
<table class="compTable">
<tr>
<th></th>
<th>Кандидат</th>
<th>Цена</th>
<th>Срок</th>
<th>Описание</th>
<th>Рейтинги/отзывы</th>
<th>Безопасные сделки</th>
<th>Решение</th>
</tr>
<div class="container mainScore">
<div class="row">
<div class="col-lg-12">
<p class="titleScore">Сравнение кандидатов по проекту</p>
</div>
<div class="titleBlockComparison disTab">
<div class="triangle1"></div>
<p>{{ object }}</p>
<table class="compTable" id="compTable">
<thead>
<tr>
<th></th>
<th>Кандидат</th>
<th>Цена</th>
<th>Срок</th>
<th>Описание</th>
<th>Рейтинги/отзывы</th>
<th>Безопасные сделки</th>
<th>Решение</th>
</tr>
</thead>
<tbody>
{% for cand in object.candidates.all %}
<tr>
<td>{{ forloop.counter }}</td>
<tr style="cursor:move;" class="items[]_{{ cand.pk }}" data-class="items[]_{{ cand.pk }}">
<td>{{ cand.position }}</td>
<td>
{{ cand.answer.contractor.get_full_name }}
{{ cand.answer.author.username }}
</td>
<td>{{ cand.answer.budget }} <i class="fa fa-rub"></i></td>
<td>
{{ cand.answer.term }}<br> <span>{{ cand.answer.term_type }}</span>
</td>
<td>
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
</td>
<td>
<ul>
<li><span>0</span></li>
@ -51,32 +54,82 @@
<small> - 0</small>
</li>
{% if cand.answer.contractor.cro %}
<li>
СРО
</li>
<li>
СРО
</li>
{% endif %}
</ul>
</td>
<td>
<span>0</span><br>
Готов работать по безопасной сделке
</td>
<td>
<div class="tableButtons disTab">
<div class="btnTab btnTab1"></div>
<a href="/test">
<div class="btnTab btnTab2"></div>
</a>
<a href="/delete">
<div class="btnTab btnTab3"></div>
</a>
<div class="btnTab btnTab4"></div>
</div>
</td>
</tr>
{% endfor %}
</table>
</div>
</tbody>
</table>
</div>
{% include 'partials/footer.html' %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block js_block %}
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E=" crossorigin="anonymous"></script>
<script type="text/javascript">
$(function () {
var fixHelper = function (e, ui) {
ui.children().each(function () {
$(this).width($(this).width());
});
return ui;
};
$("#compTable tbody").sortable({
forcePlaceholderSize: true,
forceHelperSize: true,
items: 'tr',
update: function () {
var serial = $('#compTable tbody').sortable('serialize', {key: 'items[]', attribute: 'data-class'});
console.log(serial);
$.ajax({
url: '/projects/candidate/comparison/sort/',
method: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
},
data: serial,
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (jqXHR, e) {
console.log(jqXHR);
console.log(e);
}
});
},
helper: fixHelper,
}).disableSelection();
;
});
</script>
{% endblock %}

@ -3,6 +3,7 @@ from django.views.generic import TemplateView
from .views import (
add_candidate,
sort_candidates,
contractor_portfolio_create,
ContractorPortfolioTrashView,
ContractorPortfolioUpdateView,
@ -34,6 +35,7 @@ urlpatterns = [
urls.url(r'^portfolio/(?P<pk>\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'),
urls.url(r'^candidate/add/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', add_candidate, name='add-candidate'),
urls.url(r'^candidate/comparison/sort/$', sort_candidates, name='comparison-sort'),
urls.url(r'^candidate/comparison/(?P<pk>\d+)/$', ProjectComparisonView.as_view(), name='comparison'),
urls.url(r'^offerorder/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', OfferOrderView.as_view(), name='offer-order'),

@ -11,11 +11,14 @@ from django.views.generic import ListView, DetailView, CreateView, View, UpdateV
from django.views.generic.base import ContextMixin
from pprint import pprint, pformat
import json
import pydash as _; _.map = _.map_; _.filter = _.filter_
import pydash as _;
_.map = _.map_;
_.filter = _.filter_
import re
from .mixins import LastAccessMixin
from .models import Project, ProjectFile, Portfolio, PortfolioPhoto,Candidate, Answer, AnswerFile, Realty, Order
from .models import Project, ProjectFile, Portfolio, PortfolioPhoto, Candidate, Answer, AnswerFile, Realty, Order
from archilance.mixins import BaseMixin
from users.models import User, Team
from work_sell.models import Picture
@ -57,8 +60,10 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
team = None
answer = None
try: team = contractor.team
except Team.DoesNotExist: pass
try:
team = contractor.team
except Team.DoesNotExist:
pass
if team:
answer = team.answers.first()
@ -69,7 +74,7 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
if got_answer:
context.update({'answer': answer})
else:
if request.GET.get('answer_as_team') == 'on': # TODO: Check for actual possibility to answer as a team
if request.GET.get('answer_as_team') == 'on': # TODO: Check for actual possibility to answer as a team
context.update({'answer_as_team': True})
form = self.form_class(request=request, answer_as_team=True)
else:
@ -84,7 +89,7 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
context = self.get_context_data(**kwargs)
answer_as_team = None
if request.POST.get('answer_as_team') == 'on': # TODO: Check for actual possibility to answer as a team
if request.POST.get('answer_as_team') == 'on': # TODO: Check for actual possibility to answer as a team
answer_as_team = True
if answer_as_team:
@ -255,7 +260,8 @@ class CustomerProjectCreateView(BaseMixin, View):
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
form = self.form_class(request.POST,
request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
form.is_valid()
realty = form.cleaned_data.get('realty')
@ -284,7 +290,7 @@ class CustomerProjectCreateView(BaseMixin, View):
realty.save()
realty_form.save_m2m()
project.realty = realty # Connect a realty with a project
project.realty = realty # Connect a realty with a project
project.save()
messages.info(request, 'Проект успешно создан')
@ -350,7 +356,8 @@ class CustomerProjectEditView(BaseMixin, View):
if form.is_valid() and realty_form.is_valid():
project = form.save(commit=False)
project.customer = request.user
project.files = form.cleaned_data.get('files') # TODO: Should we somehow get rid of this explicit assignment?
project.files = form.cleaned_data.get(
'files') # TODO: Should we somehow get rid of this explicit assignment?
project.save()
form.save_m2m()
@ -366,7 +373,7 @@ class CustomerProjectEditView(BaseMixin, View):
realty.save()
realty_form.save_m2m()
project.realty = realty # Connect a realty with a project
project.realty = realty # Connect a realty with a project
project.save()
messages.info(request, 'Проект успешно отредактирован')
@ -393,7 +400,7 @@ class CustomerProjectEditView(BaseMixin, View):
class ContractorPortfolioTrashView(View):
form_class = ContractorPortfolioTrashForm
def post(self,request, *args, **kwargs):
def post(self, request, *args, **kwargs):
form = self.form_class(_.merge({}, request.POST, kwargs), request=request)
if form.is_valid():
portfolio = form.cleaned_data.get('pk')
@ -405,6 +412,7 @@ class ContractorPortfolioTrashView(View):
redirect_to = request.POST.get('next')
return redirect(redirect_to)
class CustomerProjectTrashView(View):
form_class = CustomerProjectTrashForm
@ -492,7 +500,23 @@ def add_candidate(request, answer_id, project_id):
answer = Answer.objects.get(pk=answer_id)
project = Project.objects.get(pk=project_id)
candidate = Candidate.objects.create(answer=answer, project=project)
return HttpResponseRedirect(reverse('projects:detail',args=[project_id]))
return HttpResponseRedirect(reverse('projects:detail', args=[project_id]))
def sort_candidates(request):
if request.is_ajax():
items = request.POST.getlist('items[]')
i = 1
for item in items:
candidate = Candidate.objects.get(pk=item)
candidate.position = i
candidate.save()
i += 1
data = {
'success': 'ok',
}
return HttpResponse(json.dumps(data), content_type='application/json')
class OfferOrderView(View):
@ -536,9 +560,10 @@ class ContractorPortfolioUpdateView(UpdateView):
from django.views.generic import DeleteView
class PortfolioDelete(DeleteView):
model = Portfolio
success_url = reverse_lazy('users:contractor-profile')
# import code; code.interact(local=dict(globals(), **locals()))

@ -201,13 +201,14 @@
{% for ws in user.work_sell.all %}
<div class="col-lg-4">
<div class="insetCol box-sizing disTab">
<a href="{% url 'work_sell:detail' ws.pk %}">
{% thumbnail ws.get_cover "224x224" crop="center" as im %}
<div class="imgGal"
style="background:rgba(0, 0, 0, 0) url('{{ im.url }}') no-repeat scroll center center / cover ;">
<div class="imgFigure"></div>
</div>
{% endthumbnail %}
</a>
<div class="cenaImg box-sizing">
<div class="cenaImgInset">

@ -83,9 +83,10 @@
{{ form.building_classification}}
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<input type="file" name="{{ form.img.html_name }}" >
<div class="polsF1 polsF2 disTab">
{% form.ins %}
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить проект">
</div>

Loading…
Cancel
Save