remotes/origin/setup
ArturBaybulatov 10 years ago
parent 29b1d99301
commit 0d6cb8f796
  1. 2
      README.md
  2. 7
      archilance/util.py
  3. 14
      assets/index.js
  4. 35
      chat/migrations/0003_documents.py
  5. 41
      chat/migrations/0004_auto_20160804_1806.py
  6. 10
      chat/models.py
  7. 8
      common/templatetags/common_tags.py
  8. 24
      projects/migrations/0013_auto_20160804_1403.py
  9. 21
      projects/migrations/0014_auto_20160804_1754.py
  10. 8
      projects/models.py
  11. 41
      projects/templates/customer_project_edit_test.html
  12. 433
      projects/templates/project_detail.html
  13. 31
      projects/views.py
  14. 20
      users/migrations/0004_team_avatar.py
  15. 1
      users/models.py
  16. 6
      users/templates/partials/customer_profile_info_block.html

@ -23,6 +23,7 @@ python manage.py shell_plus --use-pythonrc
``` ```
---------------------------------------- ----------------------------------------
Generate data via: Generate data via:
``` ```
@ -45,6 +46,7 @@ Data generation order:
12. Reviews 12. Reviews
or here is right commands in one str: or here is right commands in one str:
``` ```
python manage.py generate_superuser && python manage.py generate_superuser &&
python manage.py generate_specializations && python manage.py generate_specializations &&

@ -82,3 +82,10 @@ def lorem(sentences=5):
), ' ') ), ' ')
return _.join(_.times(lambda i_: _.capitalize(_.join(_.sample(words, _.random(5, 30)), ' ')), sentences), '. ') return _.join(_.times(lambda i_: _.capitalize(_.join(_.sample(words, _.random(5, 30)), ' ')), sentences), '. ')
def decap(s):
if not isinstance(s, str):
raise TypeError('String expected')
return s[0].lower() + s[1:] if len(s) > 0 else s

@ -271,24 +271,24 @@ function loadRealtyDetails(realtyId) {
var $fileUploadContainer = $('#fileUploadContainer') var $fileUploadContainer = $('#fileUploadContainer')
$('#fileUploadAddBtn').on('click', function($evt) { $('#fileUploadAddBtn').on('click', function($evt) {
$fileUploadContainer.find('.file-upload-widget').last().children('.file-upload-input').click() $fileUploadContainer.find('.file-upload-widget').last().find('.file-upload-input').click()
}) })
$fileUploadContainer.on('change', '.file-upload-input', function($evt) { $fileUploadContainer.on('change', '.file-upload-input', function($evt) {
var $fileInput = $(this) var $fileInput = $(this)
var $fileUploadWidget = $fileInput.parent('.file-upload-widget') var $fileUploadWidget = $fileInput.closest('.file-upload-widget')
var filePath = $fileInput.val().replace(/\\/g, '/') var filePath = $fileInput.val().replace(/\\/g, '/')
var fileName = path.basename(filePath) var fileName = path.basename(filePath)
//var fileExt = path.extname(filePath) //var fileExt = path.extname(filePath)
var fileSize = $fileInput.get(0).files && humanFileSize($fileInput.get(0).files[0].size) var fileSize = $fileInput.get(0).files && humanFileSize($fileInput.get(0).files[0].size)
if (fileName) { if (fileName) {
$fileUploadWidget.children('.file-upload-label').text(fileName + ' ' + fileSize) $fileUploadWidget.find('.file-upload-label').text(fileName + ' ' + fileSize)
var $newFileUploadWidget = $fileUploadWidget.clone() var $newFileUploadWidget = $fileUploadWidget.clone()
$newFileUploadWidget.children('.file-upload-label').text('') $newFileUploadWidget.find('.file-upload-label').text('')
$fileUploadContainer.children('ul').first().append($newFileUploadWidget) $fileUploadContainer.find('ul').first().append($newFileUploadWidget)
$fileUploadWidget.css('display', 'block') $fileUploadWidget.css('display', 'block')
} }
@ -296,12 +296,12 @@ $fileUploadContainer.on('change', '.file-upload-input', function($evt) {
$fileUploadContainer.on('click', '.file-upload-remove-btn', function($evt) { $fileUploadContainer.on('click', '.file-upload-remove-btn', function($evt) {
var $btn = $(this) var $btn = $(this)
$btn.parent('.file-upload-widget').remove() $btn.closest('.file-upload-widget').remove()
}) })
$fileUploadContainer.on('click', '.existing-file-remove-btn', function($evt) { $fileUploadContainer.on('click', '.existing-file-remove-btn', function($evt) {
var $btn = $(this) var $btn = $(this)
$btn.parent('.existing-file-widget').remove() $btn.closest('.existing-file-widget').remove()
}) })

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-04 11:03
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('projects', '0013_auto_20160804_1403'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('users', '0003_auto_20160726_1931'),
('chat', '0002_message_team'),
]
operations = [
migrations.CreateModel(
name='Documents',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('file', models.FileField(upload_to='chat/documents/')),
('order', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='order_documents', to='projects.Order')),
('recipent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipent_documents', to=settings.AUTH_USER_MODEL)),
('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sender_documents', to=settings.AUTH_USER_MODEL)),
('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='team_documents', to='users.Team')),
],
options={
'verbose_name_plural': 'Входящие Документы',
'verbose_name': 'Входящие Документы',
},
),
]

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-04 15:06
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('chat', '0003_documents'),
]
operations = [
migrations.AlterField(
model_name='documents',
name='order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='projects.Order'),
),
migrations.AlterField(
model_name='documents',
name='team',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='users.Team'),
),
migrations.AlterField(
model_name='message',
name='order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='projects.Order'),
),
migrations.AlterField(
model_name='message',
name='team',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='users.Team'),
),
migrations.AlterField(
model_name='notes',
name='order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='projects.Order'),
),
]

@ -8,11 +8,11 @@ from users.models import User, Team
class Message(models.Model): class Message(models.Model):
text = models.TextField() text = models.TextField()
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
order = models.ForeignKey(Order, related_name='order_messages',null=True, blank=True) order = models.ForeignKey(Order, related_name='messages',null=True, blank=True)
sender = models.ForeignKey(User, related_name='sender_messages') sender = models.ForeignKey(User, related_name='sender_messages')
recipent = models.ForeignKey(User, related_name='recipent_messages') recipent = models.ForeignKey(User, related_name='recipent_messages')
private_type = models.BooleanField(default=False) private_type = models.BooleanField(default=False)
team = models.ForeignKey(Team, related_name='team_messages', null=True, blank=True) team = models.ForeignKey(Team, related_name='messages', null=True, blank=True)
def __str__(self): def __str__(self):
return self.text return self.text
@ -27,7 +27,7 @@ class Notes(models.Model):
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
sender = models.ForeignKey(User, related_name='sender_notes') sender = models.ForeignKey(User, related_name='sender_notes')
recipent = models.ForeignKey(User, related_name='recipent_notes') recipent = models.ForeignKey(User, related_name='recipent_notes')
order = models.ForeignKey(Order, related_name='order_notes', null=True, blank=True) order = models.ForeignKey(Order, related_name='notes', null=True, blank=True)
def __str__(self): def __str__(self):
return self.text return self.text
@ -39,8 +39,8 @@ class Notes(models.Model):
class Documents(models.Model): class Documents(models.Model):
file = models.FileField(upload_to='chat/documents/') file = models.FileField(upload_to='chat/documents/')
order = models.ForeignKey(Order, related_name='order_documents',null=True, blank=True) order = models.ForeignKey(Order, related_name='documents', null=True, blank=True)
team = models.ForeignKey(Team, related_name='team_documents',null=True, blank=True) team = models.ForeignKey(Team, related_name='documents', null=True, blank=True)
sender = models.ForeignKey(User, related_name='sender_documents') sender = models.ForeignKey(User, related_name='sender_documents')
recipent = models.ForeignKey(User, related_name='recipent_documents') recipent = models.ForeignKey(User, related_name='recipent_documents')

@ -57,4 +57,12 @@ def lorem(*args, **kwargs):
return util.lorem(*args, **kwargs) return util.lorem(*args, **kwargs)
@register.filter
def decap(val):
if isinstance(val, str):
return util.decap(val)
return val
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-04 11:03
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0012_merge'),
]
operations = [
migrations.RenameModel(
old_name='AnswerFiles',
new_name='AnswerFile',
),
migrations.AlterField(
model_name='answer',
name='portfolios',
field=models.ManyToManyField(blank=True, related_name='portfolios_answers', to='projects.Portfolio'),
),
]

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-04 14:54
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('projects', '0013_auto_20160804_1403'),
]
operations = [
migrations.AlterField(
model_name='order',
name='team',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to='users.Team'),
),
]

@ -141,7 +141,7 @@ class Answer(models.Model):
ordering = ('-created',) ordering = ('-created',)
class AnswerFiles(models.Model): class AnswerFile(models.Model):
answer = models.ForeignKey(Answer, related_name='files', blank=True, null=True) answer = models.ForeignKey(Answer, related_name='files', blank=True, null=True)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
file = models.FileField(upload_to='projects/answer_files') file = models.FileField(upload_to='projects/answer_files')
@ -156,15 +156,15 @@ class AnswerFiles(models.Model):
class Order(models.Model): class Order(models.Model):
contractor = models.ForeignKey(User, null=True, blank=True, related_name='orders') contractor = models.ForeignKey(User, null=True, blank=True, related_name='orders')
team = models.ForeignKey(Team, null=True, blank=True, related_name='team_orders') team = models.ForeignKey(Team, null=True, blank=True, related_name='orders')
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
project = models.OneToOneField(Project, related_name='order') project = models.OneToOneField(Project, related_name='order')
secure = models.BooleanField(default=False) secure = models.BooleanField(default=False)
status = models.BooleanField(default=False) status = models.BooleanField(default=False)
def __str__(self): def __str__(self):
return self.project.name return self.project.name
class Meta: class Meta:
verbose_name = 'Заказ' verbose_name = 'Заказ'
verbose_name_plural = 'Заказы' verbose_name_plural = 'Заказы'

@ -1,41 +0,0 @@
{% load staticfiles %}
{% load common_tags %}
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge, chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<!--<meta name='viewport' content='initial-scale=1.0, user-scalable=no, maximum-scale=1'>-->
<title>Archilance</title>
<link rel='stylesheet' href='{% static "css/bootstrap.css" %}'>
<link rel='stylesheet' href='{% static "css/dev-colors.css" %}'> <!-- Dev-time only, temporary!!! -->
</head>
<body>
{% if messages %}
{% for message in messages %}
<div class="c" style='padding: 10px; margin-bottom: 6px'>{{ message | safe }}</div>
{% endfor %}
{% endif %}
<h1>"pk": {{ pk }}</h1>
<form action="{% url 'projects:customer-project-edit' pk=pk %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}">
<button type="submit">Сохранить</button>
{% if back %}<a href='{{ back }}'>Назад</a>{% endif %}
</form>
<script src='{% static "js/jquery-2.2.3.min.js" %}'></script>
<script src='{% static "js/bootstrap.min.js" %}'></script>
</body>
</html>

@ -78,6 +78,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3 retts new-list"> <div class="col-lg-3 retts new-list">
<ul class="desListPro"> <ul class="desListPro">
<li> <li>
@ -163,16 +164,161 @@
{% if request.user.is_contractor and True %} {% if request.user.is_contractor and request.user.contractor_answers.exists %}
<form action="{% url 'projects:detail' pk=project.pk %}" method="POST" novalidate>
{% with answer=request.user.contractor_answers.first %}
<div class="b candidateBlock disTab">
<div class="candidate">
<div class="col-lg-4">
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if answer.author.avatar %}
<img src="{{ answer.author.avatar.url }}" alt="execitor-image">
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}
</div>
</a>
<p class="nameExecutor">
<a href="#">{{ answer.author.get_full_name }} [{{ answer.author.username }}]</a>
</p>
<p class="navv2">На сайте {{ answer.contractor.created }}</p>
<div class="statusUser">Свободен</div>
</div>
<div class="col-lg-3 retts">
<ul class="rettList restList2">
<li>Рейтинг: <span> 0</span></li>
<li>Безопасные сделки: <span> 0</span></li>
<li>
<a href="javascript:void(0)">Отзывы:
<span> + 0</span>
<small> 0</small>
<mark> - 0</mark>
</a>
</li>
</ul>
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
</div>
<div class="col-lg-2 listCens">
<p>
Цена:
<span>{{ answer.budget|intcomma }}</span>
<i class="fa fa-rub"></i>
</p>
<p>
Срок: <span>{{ answer.term }} {{ answer.get_term_type_display|decap }}</span>
</p>
<p>Опубликован: {{ answer.created }}</p>
</div>
<div class="col-lg-3 retts">
<a href="{% url 'projects:add-candidate' answer_id=answer.pk project_id=project.pk %}" class="candLink candLink1">
Кандидат
</a>
<a href="{% url 'projects:offer-order' answer_id=answer.pk project_id=project.pk %}" class="candLink candLink2">
предложить проект
</a>
<a href="javascript:void(0)" class="candLink candLink3">
отказ
</a>
</div>
<div class="gallMini disTab">
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
</div>
<div class="commBlock44 disTab">
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<div class="stars box-sizing">
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
</div>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
</div>
</div>
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm nameCommAct">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
<a href="javascript:void(0)" class="answerComm">
Ответить
</a>
</div>
</div>
</div>
</div>
</div>
{% endwith %}
{% elif request.user.is_contractor %}
<form action="{% url 'projects:detail' pk=project.pk %}" method="POST" enctype="multipart/form-data" novalidate>
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="next" value="{% url 'projects:detail' pk=project.pk %}"> <input type="hidden" name="next" value="{% url 'projects:detail' pk=project.pk %}">
<div class="a polsF1 disTab"> <div class="polsF1 disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Стоимость</p> <p>Стоимость <span style="color: red">{{ form.budget.errors.as_text }}</span></p>
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}"> <input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div> </div>
</div> </div>
@ -184,8 +330,8 @@
<div class="col-lg-3"> <div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Срок</p> <p>Срок <span style="color: red">{{ form.term.errors.as_text }}</span></p>
<input type="text" class="box-sizing" name="{{ form.term.html_name }}"> <input type="text" class="box-sizing" name="{{ form.term.html_name }}" value="{{ form.term.value }}">
</div> </div>
</div> </div>
@ -196,41 +342,61 @@
</div> </div>
</div> </div>
<div class="a polsF1 disTab searchF1"> <div class="polsF1 disTab searchF1">
<div class="col-lg-9"> <div class="col-lg-9">
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Текст</p> <p>Текст <span style="color: red">{{ form.text.errors.as_text }}</span></p>
<textarea name="{{ form.text.html_name }}" id="text-new"></textarea> <textarea name="{{ form.text.html_name }}" id="text-new">{{ form.text.value }}</textarea>
</div> </div>
</div> </div>
<div class="col-lg-3"></div> <div class="col-lg-3"></div>
</div> </div>
<div class="a polsF1 disTab searchF1"> <div class="polsF1 disTab searchF1">
<div class="col-lg-9"> <div class="col-lg-9">
<p>Портфолио</p> <p>Портфолио <span style="color: red">{{ form.portfolios.errors.as_text }}</span></p>
<ul> <ul>
{% for p in request.user.portfolios.all %} {% for p in request.user.portfolios.all %}
<li><input type="checkbox" name="{{ form.portfolios.html_name }}" value="{{ p.pk }}"> {{ p.name }}</li> <li>
{% endfor %} <input
type="checkbox"
name="{{ form.portfolios.html_name }}"
value="{{ p.pk }}"
{% if p.pk|str in form.portfolios.value %}checked{% endif %}>
{{ p.name }}
</li>
{% endfor %}
</ul> </ul>
</div> </div>
</div> </div>
<div class="a polsF1 disTab searchF1"> <div class="polsF1 disTab searchF1">
<div class="col-lg-9"> <div class="col-lg-9">
<button>Добавить файл</button> Не более 10 файлов общим объемом до 500 Мб <div id="fileUploadContainer">
<div>
<button type="button" id="fileUploadAddBtn">Добавить файл</button> Не более 10 файлов общим объемом до 500 Мб
</div>
<ul class="list-new-new">
<li class="file-upload-widget" style="display: none">
<input type="file" name="new_files" class="file-upload-input" style="position: absolute; top: -1000px; left: -1000px">
<span class="file-upload-label"></span>
<a href="#" onclick="return false" class="file-upload-remove-btn">&times;</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
<div class="a polsF1 disTab searchF1"> <div class="polsF1 disTab searchF1">
<div class="col-lg-9"> <div class="col-lg-9">
{{ form.secure_deal_only }} Работаю только по безопасной сделке {{ form.secure_deal_only }} Работаю только по безопасной сделке
</div> </div>
</div> </div>
<div class="a polsF1 disTab searchF1"> <div class="polsF1 disTab searchF1">
<div class="col-lg-3"> <div class="col-lg-3">
<button type="submit">Опубликовать ответ</button> <button type="submit">Опубликовать ответ</button>
</div> </div>
@ -243,235 +409,6 @@
{% elif request.user.is_contractor and False %}
{# {% with answer=tmp_answer %}#}
{# <div class="candidateBlock disTab">#}
{# <div class="candidate">#}
{# <div class="col-lg-4">#}
{# <a href="#" class="aLinkExe">#}
{# <div class="imgExecutor">#}
{# <img src="{% static 'img/profile.jpg' %}" alt="execitor-image">#}
{# </div>#}
{# </a>#}
{# <p class="nameExecutor">#}
{# <a href="#"> {{ answer.contractor.get_full_name }} []</a>#}
{# </p>#}
{# <p class="navv2">На сайте {{ answer.contractor.created }}</p>#}
{# <div class="statusUser">Свободен</div>#}
{# </div>#}
{# <div class="col-lg-3 retts">#}
{# <ul class="rettList restList2">#}
{# <li>Рейтинг: <span> 0</span></li>#}
{# <li>Безопасные сделки: <span> 0</span></li>#}
{# <li>#}
{# <a href="javascript:void(0)">Отзывы:#}
{# <span> + 0</span>#}
{# <small> 0</small>#}
{# <mark> - 0</mark>#}
{# </a>#}
{# </li>#}
{# </ul>#}
{# <div class="sroUser sroExecutor">#}
{# <div class="iconSRO"></div>#}
{# <p>Есть допуск СРО</p>#}
{# </div>#}
{# </div>#}
{# <div class="col-lg-2 listCens">#}
{# <p>Цена:#}
{# <span> {{ answer.cost|intcomma }}</span>#}
{# <i class="fa fa-rub"></i>#}
{# </p>#}
{# <p>#}
{# Срок: <span>{{ answer.term }} {{ answer.term_type }}</span>#}
{# </p>#}
{# <p>Опубликован: {{ answer.created }}</p>#}
{# </div>#}
{# <div class="col-lg-3 retts">#}
{# <a href="{% url 'projects:add-candidate' answer_id=answer.pk project_id=project.pk %}" class="candLink candLink1">#}
{# Кандидат#}
{# </a>#}
{# <a href="{% url 'projects:offer-order' answer_id=answer.pk project_id=project.pk %}" class="candLink candLink2">#}
{# предложить проект#}
{# </a>#}
{# <a href="javascript:void(0)" class="candLink candLink3">#}
{# отказ#}
{# </a>#}
{# </div>#}
{# <div class="gallMini disTab">#}
{# <div class="col-lg-3">#}
{# <div class="insetCol box-sizing disTab">#}
{# <div class="imgGal">#}
{# <div class="imgFigure"></div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="commBlock44 disTab">#}
{# <div class="comm44 disTab">#}
{# <div class="col-lg-10 col-lg-offset-1">#}
{# <p class="nameComm">#}
{# Иванов Петр Иванович#}
{# </p>#}
{# <span class="dateComm44">#}
{# 13.01.2016 / 21:05#}
{# </span>#}
{# <div class="stars box-sizing">#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# </div>#}
{# <p class="textComm44">Lorem ipsum dolor sit amet</p>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# {% endwith %}#}
<div class="b candidateBlock disTab">
<div class="candidate">
<div class="col-lg-4">
<a href="#" class="aLinkExe">
<div class="imgExecutor">
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
</div>
</a>
<p class="nameExecutor">
<a href="#">Иванов Петр Иванович [ivanov_petr]</a>
</p>
<p class="navv2">На сайте 8 лет и 3 месяца</p>
<div class="statusUser">Свободен</div>
</div>
<div class="col-lg-3 retts">
<ul class="rettList restList2">
<li>Рейтинг: <span> 1245</span></li>
<li>Безопасные сделки: <span> 5</span></li>
<li>
<a href="javascript:void(0)">Отзывы:
<span> + 385</span>
<small> 0</small>
<mark> - 0</mark>
</a>
</li>
</ul>
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
</div>
<div class="col-lg-2 listCens">
<p>Цена:
<span> 35 000</span>
<i class="fa fa-rub"></i>
</p>
<p>
Срок: <span>3 недели</span>
</p>
<p>Опубликован: 22.04.2016</p>
</div>
<div class="col-lg-3 retts">
<a href="javascript:void(0)" class="candLink candLink1">
Кандидат
</a>
<a href="javascript:void(0)" class="candLink candLink2">
предложить проект
</a>
<a href="javascript:void(0)" class="candLink candLink3">
отказ
</a>
</div>
<div class="gallMini disTab">
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
</div>
<div class="commBlock44 disTab">
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<div class="stars box-sizing">
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
</div>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
</div>
</div>
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm nameCommAct">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
<a href="javascript:void(0)" class="answerComm">
Ответить
</a>
</div>
</div>
</div>
</div>
</div>
{% elif request.user.is_customer %} {% elif request.user.is_customer %}

@ -14,7 +14,7 @@ import pydash as _; _.map = _.map_; _.filter = _.filter_
import re import re
from .mixins import LastAccessMixin from .mixins import LastAccessMixin
from .models import Project, ProjectFile, Portfolio, Candidate, Answer, Realty, Order from .models import Project, ProjectFile, Portfolio, Candidate, Answer, AnswerFile, Realty, Order
from archilance.mixins import BaseMixin from archilance.mixins import BaseMixin
from users.models import User from users.models import User
@ -42,10 +42,6 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
project = get_object_or_404(Project, pk=kwargs.get('pk')) project = get_object_or_404(Project, pk=kwargs.get('pk'))
context.update({'project': project}) context.update({'project': project})
# context.update({'tmp_answer': Answer.objects.order_by('?').first()})
# import code; code.interact(local=dict(globals(), **locals()))
if request.user.is_authenticated() and request.user.is_contractor(): if request.user.is_authenticated() and request.user.is_contractor():
form = self.form_class(request=request) form = self.form_class(request=request)
context.update({'form': form}) context.update({'form': form})
@ -61,11 +57,17 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
context.update({'project': project}) context.update({'project': project})
if form.is_valid(): if form.is_valid():
print('###############################################') answer = form.save(commit=False)
pprint(form.cleaned_data) answer.project = project
print('###############################################') answer.author = request.user
answer.save()
form.save_m2m()
messages.info(request, 'Форма ОК') for file in request.FILES.getlist('new_files'):
if len(file.name) <= 255:
AnswerFile.objects.create(file=file, name=file.name, answer=answer)
messages.info(request, 'Отклик успешно размещён')
redirect_to = request.POST.get('next') redirect_to = request.POST.get('next')
return redirect(redirect_to) return redirect(redirect_to)
else: else:
@ -199,7 +201,7 @@ class CustomerProjectCreateView(BaseMixin, View):
template_name = 'customer_project_create.html' template_name = 'customer_project_create.html'
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated() and request.user.is_customer() and request.user.pk == int(kwargs.get('pk')): if request.user.is_authenticated() and request.user.is_customer():
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
else: else:
return HttpResponseForbidden('403 Forbidden') return HttpResponseForbidden('403 Forbidden')
@ -214,7 +216,7 @@ class CustomerProjectCreateView(BaseMixin, View):
return render(request, self.template_name, context) return render(request, self.template_name, context)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request.FILES, request=request) form = self.form_class(request.POST, request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
form.is_valid() form.is_valid()
realty = form.cleaned_data.get('realty') realty = form.cleaned_data.get('realty')
@ -233,8 +235,7 @@ class CustomerProjectCreateView(BaseMixin, View):
Order.objects.create(project=project) Order.objects.create(project=project)
for file in request.FILES.getlist('new_files'): for file in request.FILES.getlist('new_files'):
proj_file = ProjectFile.objects.create(file=file, project=project) ProjectFile.objects.create(file=file, project=project)
proj_file.save()
if realty: if realty:
realty_form.save() realty_form.save()
@ -310,7 +311,7 @@ class CustomerProjectEditView(BaseMixin, View):
if form.is_valid() and realty_form.is_valid(): if form.is_valid() and realty_form.is_valid():
project = form.save(commit=False) project = form.save(commit=False)
project.customer = request.user project.customer = request.user
project.files = form.cleaned_data.get('files') # TODO: 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() project.save()
form.save_m2m() form.save_m2m()
@ -366,7 +367,7 @@ class CustomerProjectTrashView(View):
project = form.cleaned_data.get('pk') project = form.cleaned_data.get('pk')
project.state = 'trashed' project.state = 'trashed'
project.save() project.save()
messages.info(req, 'Проект перемещён в корзину') messages.info(req, 'Проект перемещён в корзину')
else: else:
messages.info(req, 'Произошла ошибка: <pre>{msg}</pre>'.format(msg=pformat(form.errors))) messages.info(req, 'Произошла ошибка: <pre>{msg}</pre>'.format(msg=pformat(form.errors)))

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-04 16:00
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0003_auto_20160726_1931'),
]
operations = [
migrations.AddField(
model_name='team',
name='avatar',
field=models.ImageField(blank=True, upload_to='teams/avatars/'),
),
]

@ -185,6 +185,7 @@ class User(AbstractBaseUser, PermissionsMixin):
class Team(models.Model): class Team(models.Model):
answers = GenericRelation('projects.Answer') answers = GenericRelation('projects.Answer')
avatar = models.ImageField(upload_to='teams/avatars/', blank=True)
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
owner = models.OneToOneField(User, related_name='team', blank=True, null=True) owner = models.OneToOneField(User, related_name='team', blank=True, null=True)

@ -5,7 +5,11 @@
<div class="col-lg-3 divCol3"> <div class="col-lg-3 divCol3">
<div class="avatar new-mar"> <div class="avatar new-mar">
<div class="avatarInset"> <div class="avatarInset">
<img src="{{ customer.avatar.url }}" alt="profile-image"> {% if customer.avatar %}
<img src="{{ customer.avatar.url }}" alt="profile-image">
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="profile-image">
{% endif %}
</div> </div>
</div> </div>
</div> </div>

Loading…
Cancel
Save