From 18f52979114bdc15d93ae9f9d9cb02171544e872 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Wed, 14 Sep 2016 17:33:03 +0300 Subject: [PATCH 1/3] Fixes --- projects/forms.py | 21 +++++---- projects/migrations/0031_merge.py | 16 +++++++ projects/models.py | 6 +-- projects/urls.py | 2 +- projects/views.py | 6 +-- work_sell/forms.py | 31 ++++++++---- work_sell/migrations/0014_merge.py | 16 +++++++ work_sell/models.py | 10 ++-- work_sell/templates/worksell_edit.html | 65 ++++++++++++++++++++++++-- work_sell/views.py | 26 ++++++++++- 10 files changed, 161 insertions(+), 38 deletions(-) create mode 100644 projects/migrations/0031_merge.py create mode 100644 work_sell/migrations/0014_merge.py diff --git a/projects/forms.py b/projects/forms.py index 0052f6b..6196118 100644 --- a/projects/forms.py +++ b/projects/forms.py @@ -207,20 +207,23 @@ class PortfolioEditForm(forms.ModelForm): fields = ( 'building_classification', 'construction_type', + 'specialization', + + 'budget', 'currency', + 'description', 'name', - 'photos', + 'term', 'term_type', + 'worksell', ) - # fields = '__all__' - # - # widgets = { - # 'construction_type': forms.Select(attrs={'class': 'selectpicker'}), - # 'building_classification': forms.Select(attrs={'class': 'selectpicker'}), - # 'currency': forms.Select(attrs={'class': 'selectpicker'}), - # 'term_type': forms.Select(attrs={'class': 'selectpicker'}), - # } + widgets = { + 'construction_type': forms.Select(attrs={'class': 'selectpicker'}), + 'building_classification': forms.Select(attrs={'class': 'selectpicker'}), + 'currency': forms.Select(attrs={'class': 'selectpicker'}), + 'term_type': forms.Select(attrs={'class': 'selectpicker'}), + } def __init__(self, *args, **kwargs): # self.request = kwargs.pop('request') diff --git a/projects/migrations/0031_merge.py b/projects/migrations/0031_merge.py new file mode 100644 index 0000000..bc7937d --- /dev/null +++ b/projects/migrations/0031_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-14 13:00 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0030_auto_20160912_1912'), + ('projects', '0030_auto_20160912_1305'), + ] + + operations = [ + ] diff --git a/projects/models.py b/projects/models.py index 95b52be..2432b5d 100644 --- a/projects/models.py +++ b/projects/models.py @@ -119,7 +119,7 @@ class Project(models.Model, HitCountMixin): class ProjectFile(models.Model): - file = models.FileField(upload_to='projects/project_files') + file = models.FileField(upload_to='projects/project_files/') project = models.ForeignKey(Project, related_name='files', blank=True, null=True) class Meta: @@ -189,7 +189,7 @@ class AnswerMessage(models.Model): class AnswerFile(models.Model): answer = models.ForeignKey(Answer, related_name='files', blank=True, null=True) name = models.CharField(max_length=255) - file = models.FileField(upload_to='projects/answer_files') + file = models.FileField(upload_to='projects/answer_files/') class Meta: verbose_name = 'Файл для отклика' @@ -336,7 +336,7 @@ class Portfolio(models.Model): class PortfolioPhoto(models.Model): - img = models.ImageField(upload_to='projects/portfolio') + img = models.ImageField(upload_to='projects/portfolio/') portfolio = models.ForeignKey(Portfolio, related_name='photos') class Meta: diff --git a/projects/urls.py b/projects/urls.py index bb4bef6..41a786e 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -47,7 +47,7 @@ urlpatterns = [ urls.url(r'^answer/move/archive/$', ContractorAnswerArchiveView.as_view(), name='contractor-answer-archive'), urls.url(r'^portfolio/create/$', contractor_portfolio_create, name='contractor-portfolio-create'), - urls.url(r'^portfolio/(?P\d+)/?$', PortfolioDetail.as_view(), name='contractor-portfolio-detail'), + urls.url(r'^portfolio/(?P\d+)/$', PortfolioDetail.as_view(), name='contractor-portfolio-detail'), urls.url(r'^portfolio/(?P\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'), urls.url(r'^portfolio/(?P\d+)/trash/$', ContractorPortfolioTrashView.as_view(), name='contractor-portfolio-trash'), diff --git a/projects/views.py b/projects/views.py index 4beaaeb..5c336bd 100644 --- a/projects/views.py +++ b/projects/views.py @@ -762,7 +762,7 @@ class ContractorPortfolioUpdateView(BaseMixin, UpdateView): template_name = 'contractor_portfolio_edit.html' def get_success_url(self): - return reverse('users:contractor-profile',kwargs={'pk':self.object.user_id}) + return reverse('projects:contractor-portfolio-detail', kwargs={'pk': self.object.pk}) def form_valid(self, form): portfolio = form.instance @@ -781,11 +781,9 @@ class ContractorPortfolioUpdateView(BaseMixin, UpdateView): live_images = form.cleaned_data['live_images'] - # import code; code.interact(local=dict(globals(), **locals())) - for live_image in live_images: new_image = ContentFile(live_image.file.read()) - # new_image.name = live_image.file.name + new_image.name = live_image.file.name PortfolioPhoto.objects.create(img=new_image, portfolio=portfolio) diff --git a/work_sell/forms.py b/work_sell/forms.py index 54a829b..00252f5 100644 --- a/work_sell/forms.py +++ b/work_sell/forms.py @@ -1,8 +1,8 @@ import itertools from django import forms -from common.models import Location -from .models import WorkSell +from common.models import Location, LiveImageUpload +from .models import WorkSell, WorkSellPhoto from specializations.models import Specialization @@ -17,19 +17,32 @@ class ContractorWorkSellTrashForm(forms.Form): class WorkSellForm(forms.ModelForm): + # Define a form field manually for a reverse model vield: + + photos = forms.ModelMultipleChoiceField( + queryset=WorkSellPhoto.objects.none(), + widget=forms.CheckboxSelectMultiple, + required=False, + ) + + live_images = forms.ModelMultipleChoiceField( + queryset=LiveImageUpload.objects.all(), + widget=forms.CheckboxSelectMultiple, + required=False, + ) + class Meta: model = WorkSell fields = ( - 'budget', 'building_classification', 'construction_type', - 'contractor', + 'specialization', + + 'budget', 'currency', 'description', - 'location', 'name', - 'specialization', 'term', 'term_type', ) @@ -43,10 +56,8 @@ class WorkSellForm(forms.ModelForm): def __init__(self, *args, **kwargs): # self.request = kwargs.pop('request') super().__init__(*args, **kwargs) - - self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() - self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() - # self.fields['location'].queryset = Location.objects # Migrate with this enabled + + self.fields['photos'].queryset = self.instance.photos.all() class WorkSellFilterForm(forms.ModelForm): diff --git a/work_sell/migrations/0014_merge.py b/work_sell/migrations/0014_merge.py new file mode 100644 index 0000000..a04c6b1 --- /dev/null +++ b/work_sell/migrations/0014_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-14 13:00 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('work_sell', '0013_auto_20160912_1305'), + ('work_sell', '0013_auto_20160912_1912'), + ] + + operations = [ + ] diff --git a/work_sell/models.py b/work_sell/models.py index b4c412b..bcddff8 100644 --- a/work_sell/models.py +++ b/work_sell/models.py @@ -54,19 +54,19 @@ class WorkSell(models.Model): class WorkSellPhoto(models.Model): - img = ImageField(upload_to='worksell/worksell') + img = ImageField(upload_to='worksell/worksell/') worksell = models.ForeignKey(WorkSell, related_name='photos') - def __str__(self): - return self.worksell.name - class Meta: verbose_name = 'Изображение Готовая работа' verbose_name_plural = 'Изображения Готовые работы' + def __str__(self): + return self.img and self.img.url or str(self.img) + class Picture(models.Model): - file = models.ImageField(upload_to='worksell/pictures') + file = models.ImageField(upload_to='worksell/pictures/') slug = models.SlugField(max_length=50, blank=True) def __str__(self): diff --git a/work_sell/templates/worksell_edit.html b/work_sell/templates/worksell_edit.html index 6681788..c4b7217 100644 --- a/work_sell/templates/worksell_edit.html +++ b/work_sell/templates/worksell_edit.html @@ -1,6 +1,21 @@ {% extends 'partials/base.html' %} -{% load common_tags %} +{% load thumbnail %} + + +{% block head_css %} + +{% endblock %} {% block content %} {% include 'partials/header.html' %} @@ -26,7 +41,8 @@

Специализации

- + +
@@ -43,9 +59,9 @@
- - +

Бюджет{{ form.budget.errors.as_text }}

@@ -82,6 +98,47 @@

Классификация здания

{{ form.building_classification}}
+ +
+

Фотографии

+ + {% for photo in form.photos.field.queryset.all %} +
+
+ × + + {% thumbnail photo.img "200x200" crop="center" as img %} + + {% endthumbnail %} +
+ + +
+ {% endfor %} + + + +
+ + +
diff --git a/work_sell/views.py b/work_sell/views.py index a722b71..955c8dc 100644 --- a/work_sell/views.py +++ b/work_sell/views.py @@ -178,13 +178,35 @@ class WorkSellUpdateView(UpdateView): template_name = 'worksell_edit.html' def dispatch(self, request, *args, **kwargs): - # import code; code.interact(local=dict(globals(), **locals())) if self.get_object().contractor_id != request.user.pk: return HttpResponseForbidden('403 Forbidden') return super().dispatch(request, *args, **kwargs) def get_success_url(self): - return reverse('work_sell:list') + return reverse('work_sell:detail', kwargs={'pk': self.object.pk}) + + def form_valid(self, form): + worksell = form.instance + + photos = form.cleaned_data['photos'] + + WorkSellPhoto.objects.filter(worksell=worksell).delete() + + for photo in photos: + WorkSellPhoto.objects.create(img=photo.img, worksell=worksell) + + live_images = form.cleaned_data['live_images'] + + for live_image in live_images: + new_image = ContentFile(live_image.file.read()) + new_image.name = live_image.file.name + + WorkSellPhoto.objects.create(img=new_image, worksell=worksell) + + live_image.file.delete() + live_image.delete() + + return super().form_valid(form) class WorkSellDeleteView(DeleteView): From 5205b388ed565266541f3380a1b8086af1d53683 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Thu, 15 Sep 2016 17:25:28 +0300 Subject: [PATCH 2/3] Fixes --- api/views.py | 18 +++- archilance/settings/base.py | 2 +- assets/index.js | 38 +++++--- assets/js/chat.js | 2 +- chat/filters.py | 17 ++-- common/filters.py | 16 +++- common/serializers.py | 28 ++++-- projects/filters.py | 61 ++++++++++--- projects/serializers.py | 113 ++++++++++++++++-------- reviews/filters.py | 10 +-- specializations/filters.py | 7 +- templates/partials/base.html | 2 +- users/filters.py | 4 +- users/templates/contractor_profile.html | 3 +- work_sell/filters.py | 3 +- 15 files changed, 230 insertions(+), 94 deletions(-) diff --git a/api/views.py b/api/views.py index 27d998f..1fd78be 100755 --- a/api/views.py +++ b/api/views.py @@ -13,7 +13,7 @@ from projects.serializers import ( from projects.filters import ( ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet, OrderFilterSet, - PortfolioPhotoFilterSet, + PortfolioPhotoFilterSet, AnswerFilterSet, ) from specializations.models import Specialization @@ -22,7 +22,7 @@ from specializations.filters import SpecializationFilterSet from users.models import User, ContractorResumeFiles, ContractorResume, Team from users.serializers import UserSerializer, ContractorResumeFilesSerializer, ContractorResumeSerializer, TeamSerializer -from users.filters import UserFilterSet, ContractorResumeFilesFilterSet, ContractorResumeFilterSet +from users.filters import UserFilterSet, TeamFilterSet, ContractorResumeFilesFilterSet, ContractorResumeFilterSet from common.models import Location from common.serializers import LocationSerializer @@ -92,6 +92,16 @@ class ProjectViewSet(ModelViewSet): serializer_class = ProjectSerializer filter_class = ProjectFilterSet + def get_queryset(self): + qs = super().get_queryset() + + x_no_contractor_answer = self.request.GET.get('x_no_contractor_answer', '') + + if x_no_contractor_answer.isdecimal(): + qs = qs.exclude(answers__object_id=x_no_contractor_answer, answers__content_type__model='user') + + return qs + class NoteViewSet(ModelViewSet): queryset = Notes.objects.all() @@ -220,10 +230,10 @@ class WorkSellPhotoViewSet(ModelViewSet): class AnswerViewSet(ModelViewSet): queryset = Answer.objects.all() serializer_class = AnswerSerializer - # filter_class = AnswerFilterSet + filter_class = AnswerFilterSet class TeamViewSet(ModelViewSet): queryset = Team.objects.all() serializer_class = TeamSerializer - # filter_class = TeamFilterSet + filter_class = TeamFilterSet diff --git a/archilance/settings/base.py b/archilance/settings/base.py index 42c8493..86b3daf 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -266,7 +266,7 @@ if DEBUG: EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' PAGE_SIZE = 10 # Non-api page size (regular views) -API_PAGE_SIZE = 1000 # Django REST framework +API_PAGE_SIZE = 100 # Django REST framework REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ diff --git a/assets/index.js b/assets/index.js index e24700b..8d2e35f 100644 --- a/assets/index.js +++ b/assets/index.js @@ -257,30 +257,42 @@ function initContractorSelect($select, excludeIds) { // Order offer project select --------------------------------------------- - -var projectSelectOptions = { - language: 'ru', - placeholder: 'Выберите проект', // Required by `allowClear` - allowClear: true, -} - -function initProjectSelect($select, customerId) { - return $.ajax({url: '/api/projects/?state=active&customer=' + customerId, method: 'GET', dataType: 'json'}) - .then(function(res) { +;(function() { + var projectSelectOptions = { + language: 'ru', + placeholder: 'Выберите проект', // Required by `allowClear` + allowClear: true, + } + + function initProjectSelect($select, customerId, contractorId) { + var urlObj = new URI('/api/projects/') + + urlObj.setQuery({ + state: 'active', + customer: customerId, + order__contractor__isnull: true, + order__team__isnull: true, + x_no_contractor_answer: contractorId, + }) + + return $.get(urlObj.href()).then(function(res) { var projects = res.results $select.select2(_.merge(projectSelectOptions, { data: _.map(function(project) { return { id: project.id, - text: project.name, + //text: project.name, + text: format('%s (%s)', project.name, project.id), // Tmp origItem: project, } }, projects), })) }) -} - + } + + window.initProjectSelect = initProjectSelect +}()) diff --git a/assets/js/chat.js b/assets/js/chat.js index 5ee15de..f770568 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/chat/filters.py b/chat/filters.py index 6e878f7..0b3da56 100644 --- a/chat/filters.py +++ b/chat/filters.py @@ -5,6 +5,7 @@ from .models import Message, Notes, Documents # # class DocumentsFilterSet(FilterSet): # file = AllLookupsFilter() +# id = AllLookupsFilter() # # sender = RelatedFilter('users.filters.UserFilterSet') # # recipent = RelatedFilter('users.filters.UserFilterSet') # # order = RelatedFilter('projects.filters.OrderFilterSet') @@ -15,13 +16,15 @@ from .models import Message, Notes, Documents class MessageFilterSet(FilterSet): - text = AllLookupsFilter() created = AllLookupsFilter() - sender = RelatedFilter('users.filters.UserFilterSet') - recipent = RelatedFilter('users.filters.UserFilterSet') + id = AllLookupsFilter() private_type = AllLookupsFilter() - team = RelatedFilter('users.filters.TeamFilterSet') + text = AllLookupsFilter() + order = RelatedFilter('projects.filters.OrderFilterSet') + recipent = RelatedFilter('users.filters.UserFilterSet') + sender = RelatedFilter('users.filters.UserFilterSet') + team = RelatedFilter('users.filters.TeamFilterSet') class Meta: model = Message @@ -39,10 +42,12 @@ class DocumentFilterSet(FilterSet): class NoteFilterSet(FilterSet): - text = AllLookupsFilter() created = AllLookupsFilter() - sender = RelatedFilter('users.filters.UserFilterSet') + id = AllLookupsFilter() + text = AllLookupsFilter() + recipent = RelatedFilter('users.filters.UserFilterSet') + sender = RelatedFilter('users.filters.UserFilterSet') class Meta: model = Notes diff --git a/common/filters.py b/common/filters.py index fbfd842..17689f8 100644 --- a/common/filters.py +++ b/common/filters.py @@ -1,17 +1,29 @@ +from django.contrib.contenttypes.models import ContentType from rest_framework_filters import FilterSet, AllLookupsFilter, RelatedFilter + from .models import Location class LocationFilterSet(FilterSet): - children = RelatedFilter('common.filters.LocationFilterSet') id = AllLookupsFilter() level = AllLookupsFilter() lft = AllLookupsFilter() name = AllLookupsFilter() - parent = RelatedFilter('common.filters.LocationFilterSet') rght = AllLookupsFilter() tree_id = AllLookupsFilter() type = AllLookupsFilter() + + children = RelatedFilter('common.filters.LocationFilterSet') + parent = RelatedFilter('common.filters.LocationFilterSet') class Meta: model = Location + + +class ContentTypeFilterSet(FilterSet): + app_label = AllLookupsFilter() + id = AllLookupsFilter() + model = AllLookupsFilter() + + class Meta: + model = ContentType diff --git a/common/serializers.py b/common/serializers.py index cc37b8c..9c455e4 100644 --- a/common/serializers.py +++ b/common/serializers.py @@ -1,3 +1,4 @@ +from django.contrib.contenttypes.models import ContentType from rest_framework.serializers import ModelSerializer from .models import Location @@ -8,15 +9,15 @@ class NestedLocationSerializer(ModelSerializer): model = Location fields = ( + 'children', 'id', + 'level', + 'lft', 'name', - 'children', 'parent', - 'type', - 'lft', 'rght', - 'level', 'tree_id', + 'type', ) @@ -28,13 +29,24 @@ class LocationSerializer(ModelSerializer): model = Location fields = ( + 'children', 'id', + 'level', + 'lft', 'name', - 'children', 'parent', - 'type', - 'lft', 'rght', - 'level', 'tree_id', + 'type', + ) + + +class ContentTypeSerializer(ModelSerializer): + class Meta: + model = ContentType + + fields = ( + 'app_label', + 'id', + 'model', ) diff --git a/projects/filters.py b/projects/filters.py index 5f20c98..b111a72 100755 --- a/projects/filters.py +++ b/projects/filters.py @@ -1,6 +1,16 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter -from .models import Project, Stage, Order, Realty, BuildingClassfication, ConstructionType, Portfolio, PortfolioPhoto +from .models import ( + Answer, + BuildingClassfication, + ConstructionType, + Order, + Portfolio, + PortfolioPhoto, + Project, + Realty, + Stage, +) class BuildingClassficationFilterSet(FilterSet): @@ -26,6 +36,7 @@ class ProjectFilterSet(FilterSet): cro = AllLookupsFilter() currency = AllLookupsFilter() deal_type = AllLookupsFilter() + id = AllLookupsFilter() name = AllLookupsFilter() price_and_term_required = AllLookupsFilter() state = AllLookupsFilter() @@ -34,7 +45,9 @@ class ProjectFilterSet(FilterSet): text = AllLookupsFilter() work_type = AllLookupsFilter() + answers = RelatedFilter('projects.filters.AnswerFilterSet') customer = RelatedFilter('users.filters.UserFilterSet') + order = RelatedFilter('projects.filters.OrderFilterSet') realty = RelatedFilter('projects.filters.RealtyFilterSet') specialization = RelatedFilter('specializations.filters.SpecializationFilterSet') @@ -42,31 +55,58 @@ class ProjectFilterSet(FilterSet): model = Project -class OrderFilterSet(FilterSet): - id = AllLookupsFilter() - contractor = RelatedFilter('users.filters.UserFilterSet') - team = RelatedFilter('users.filters.TeamFilterSet') +class AnswerFilterSet(FilterSet): + budget = AllLookupsFilter() created = AllLookupsFilter() + currency = AllLookupsFilter() + id = AllLookupsFilter() + is_archive = AllLookupsFilter() + object_id = AllLookupsFilter() + rejected = AllLookupsFilter() + secure_deal_only = AllLookupsFilter() + term = AllLookupsFilter() + term_type = AllLookupsFilter() + + # author = ... # ??? + + # messages = RelatedFilter('...') + content_type = RelatedFilter('common.filters.ContentTypeFilterSet') + contractors = RelatedFilter('users.filters.UserFilterSet') + portfolios = RelatedFilter('projects.filters.PortfolioFilterSet') project = RelatedFilter('projects.filters.ProjectFilterSet') + teams = RelatedFilter('users.filters.TeamFilterSet') + + class Meta: + model = Answer + + +class OrderFilterSet(FilterSet): + created = AllLookupsFilter() + id = AllLookupsFilter() secure = AllLookupsFilter() status = AllLookupsFilter() + + contractor = RelatedFilter('users.filters.UserFilterSet') + project = RelatedFilter('projects.filters.ProjectFilterSet') + team = RelatedFilter('users.filters.TeamFilterSet') class Meta: model = Order class StageFilterSet(FilterSet): + cost = AllLookupsFilter() + cost_type = AllLookupsFilter() id = AllLookupsFilter() + is_paid = AllLookupsFilter() name = AllLookupsFilter() + pos = AllLookupsFilter() result = AllLookupsFilter() - cost = AllLookupsFilter() + status = AllLookupsFilter() term = AllLookupsFilter() - cost_type = AllLookupsFilter() term_type = AllLookupsFilter() - status = AllLookupsFilter() - pos = AllLookupsFilter() + order = RelatedFilter('projects.filters.OrderFilterSet') - is_paid = AllLookupsFilter() class Meta: model = Stage @@ -87,6 +127,7 @@ class RealtyFilterSet(FilterSet): class PortfolioPhotoFilterSet(FilterSet): id = AllLookupsFilter() + portfolio = RelatedFilter('projects.filters.PortfolioFilterSet') # img = ??? diff --git a/projects/serializers.py b/projects/serializers.py index 07658ad..e17b96d 100755 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -3,11 +3,40 @@ from generic_relations.relations import GenericRelatedField from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField, ReadOnlyField from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile -from common.serializers import LocationSerializer +from common.serializers import LocationSerializer, ContentTypeSerializer from specializations.serializers import SpecializationSerializer from users.models import User, Team from users.serializers import UserSerializer, TeamSerializer + +class AnswerFileSerializer(ModelSerializer): + file = FileField() + + class Meta: + model = AnswerFile + + fields = ( + 'file', + 'id', + 'name', + # 'answer', + ) + + +class PortfolioPhotoSerializer(ModelSerializer): + img = ImageField() + portfolio_id = PrimaryKeyRelatedField(read_only=True, source='portfolio') + + class Meta: + model = PortfolioPhoto + + fields = ( + 'id', + 'img', + 'portfolio_id', + ) + + class BuildingClassficationSerializer(ModelSerializer): class Meta: model = BuildingClassfication @@ -93,16 +122,53 @@ class OrderSerializer_(ModelSerializer): ) +class AnswerSerializer_(ModelSerializer): + project_id = PrimaryKeyRelatedField(read_only=True, source='project') + portfolio_ids = PrimaryKeyRelatedField(read_only=True, source='portfolios', many=True) + + content_type = ContentTypeSerializer() + files = AnswerFileSerializer(many=True) + + author = GenericRelatedField({ + User: UserSerializer(), + Team: TeamSerializer() + }) + + class Meta: + model = Answer + + fields = ( + 'budget', + 'created', + 'currency', + 'id', + 'is_archive', + 'object_id', + 'portfolio_ids', + 'project_id', + 'rejected', + 'secure_deal_only', + 'term', + 'term_type', + + 'author', # Generic related field + 'content_type', + 'files', + ) + + class ProjectSerializer(ModelSerializer): + answers = AnswerSerializer_(many=True) customer = UserSerializer() - specialization = SpecializationSerializer() - realty = RealtySerializer() order = OrderSerializer_() # TODO: Can't serialize a reverse/reciprocal relation + realty = RealtySerializer() + specialization = SpecializationSerializer() class Meta: model = Project - + fields = ( + 'answers', 'budget', 'budget_by_agreement', 'created', @@ -158,25 +224,10 @@ class OrderSerializer(ModelSerializer): return False -class PortfolioPhotoSerializer(ModelSerializer): - img = ImageField() - portfolio_id = PrimaryKeyRelatedField(read_only=True, source='portfolio') - - class Meta: - model = PortfolioPhoto - - fields = ( - 'id', - 'img', - 'portfolio_id', - ) - - class PortfolioSerializer(ModelSerializer): # answers = AnswerSerializer(many=True) building_classification = BuildingClassficationSerializer() construction_type = ConstructionTypeSerializer() - id = ReadOnlyField() location = LocationSerializer() photos = PortfolioPhotoSerializer(many=True) specialization = SpecializationSerializer() @@ -204,24 +255,11 @@ class PortfolioSerializer(ModelSerializer): ) -class AnswerFileSerializer(ModelSerializer): - file = FileField() - - class Meta: - model = AnswerFile - - fields = ( - 'file', - 'id', - 'name', - # 'answer', - ) - - class AnswerSerializer(ModelSerializer): + content_type = ContentTypeSerializer() files = AnswerFileSerializer(many=True) portfolios = PortfolioSerializer(many=True) - project = ProjectSerializer + project = ProjectSerializer() author = GenericRelatedField({ User: UserSerializer(), @@ -236,15 +274,18 @@ class AnswerSerializer(ModelSerializer): 'created', 'currency', 'id', + 'is_archive', + 'object_id', + 'rejected', 'secure_deal_only', 'term', 'term_type', - 'text', + 'author', # Generic related field + 'content_type', 'files', 'portfolios', 'project', - 'author', # Generic related field # 'candidates', ) diff --git a/reviews/filters.py b/reviews/filters.py index db9119c..7f65b47 100644 --- a/reviews/filters.py +++ b/reviews/filters.py @@ -4,15 +4,15 @@ from .models import Review class ReviewFilterSet(FilterSet): + created = AllLookupsFilter() + id = AllLookupsFilter() text = AllLookupsFilter() type = AllLookupsFilter() - created = AllLookupsFilter() - from_customer = RelatedFilter('users.filters.UserFilterSet') + from_contractor = RelatedFilter('users.filters.UserFilterSet') - target_customer = RelatedFilter('users.filters.UserFilterSet') + from_customer = RelatedFilter('users.filters.UserFilterSet') target_contractor = RelatedFilter('users.filters.UserFilterSet') + target_customer = RelatedFilter('users.filters.UserFilterSet') class Meta: model = Review - - diff --git a/specializations/filters.py b/specializations/filters.py index 53e667c..b690c10 100755 --- a/specializations/filters.py +++ b/specializations/filters.py @@ -2,15 +2,16 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter from .models import Specialization class SpecializationFilterSet(FilterSet): - children = RelatedFilter('specializations.filters.SpecializationFilterSet') id = AllLookupsFilter() level = AllLookupsFilter() lft = AllLookupsFilter() name = AllLookupsFilter() - parent = RelatedFilter('specializations.filters.SpecializationFilterSet') - projects = RelatedFilter('projects.filters.ProjectFilterSet') rght = AllLookupsFilter() tree_id = AllLookupsFilter() + children = RelatedFilter('specializations.filters.SpecializationFilterSet') + parent = RelatedFilter('specializations.filters.SpecializationFilterSet') + projects = RelatedFilter('projects.filters.ProjectFilterSet') + class Meta: model = Specialization diff --git a/templates/partials/base.html b/templates/partials/base.html index 6530a3f..75da402 100644 --- a/templates/partials/base.html +++ b/templates/partials/base.html @@ -86,7 +86,7 @@ if ((queryString.indexOf('/chat') != 0) && (queryString.indexOf('/users/contractor-office/510/work-projects') != 0)) { 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/users/filters.py b/users/filters.py index bc29452..5055a73 100755 --- a/users/filters.py +++ b/users/filters.py @@ -47,8 +47,8 @@ class TeamFilterSet(FilterSet): class ContractorResumeFilterSet(FilterSet): id = AllLookupsFilter() - text = AllLookupsFilter() resume_file = AllLookupsFilter() + text = AllLookupsFilter() class Meta: model = ContractorResume @@ -56,8 +56,8 @@ class ContractorResumeFilterSet(FilterSet): class ContractorResumeFilesFilterSet(FilterSet): id = AllLookupsFilter() - title = AllLookupsFilter() img = AllLookupsFilter() + title = AllLookupsFilter() resume = RelatedFilter('users.filters.ContractorResumeFilterSet') diff --git a/users/templates/contractor_profile.html b/users/templates/contractor_profile.html index 4a5fed1..2f089db 100644 --- a/users/templates/contractor_profile.html +++ b/users/templates/contractor_profile.html @@ -738,6 +738,7 @@ {% if request.user.is_customer %} var customerId = {{ request.user.pk }} + var contractorId = {{ contractor.pk }} var $projectSelectionModal = $('#projectSelectionModal') var projectUrl_ = '/projects/%id%/' var projectOrderChatUrl_ = '/chat/#order%orderId%' @@ -751,7 +752,7 @@ $that.data('modalOpenButton', $modalOpenButton) - initProjectSelect($projectSelect, customerId) + initProjectSelect($projectSelect, customerId, contractorId) }) diff --git a/work_sell/filters.py b/work_sell/filters.py index 50faa3c..a8e7137 100644 --- a/work_sell/filters.py +++ b/work_sell/filters.py @@ -15,9 +15,10 @@ class WorkSellFilter(django_filters.FilterSet): class WorkSellPhotoFilterSet(FilterSet): id = AllLookupsFilter() - work_sell = RelatedFilter('work_sell.filters.WorkSellFilterSet') # img = ??? + work_sell = RelatedFilter('work_sell.filters.WorkSellFilterSet') + class Meta: model = WorkSellPhoto From d9b6897601c438ab9ab9bb7f73bc8ef2e021d483 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Thu, 15 Sep 2016 18:24:30 +0300 Subject: [PATCH 3/3] #ARC-14 (18, 23, 24) --- projects/templates/project_detail.html | 67 ++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/projects/templates/project_detail.html b/projects/templates/project_detail.html index 1d49102..d954d47 100644 --- a/projects/templates/project_detail.html +++ b/projects/templates/project_detail.html @@ -109,7 +109,7 @@
{% if request.user.is_contractor and not answer %} - + Ответить на проект @@ -283,6 +283,18 @@ отказ + + {% if project.order.contractor and project.order.contractor == answer.author %} + Перейти к обсуждению + {% elif project.order.team and project.order.team == answer.author %} + Перейти к обсуждению + {% else %} + {% if answer.author|class_name == 'User' %} + Перейти к обсуждению + {% elif answer.author|class_name == 'Team'%} + Перейти к обсуждению + {% endif %} + {% endif %}
@@ -361,7 +373,7 @@
{% else %} -
+ {% csrf_token %} @@ -655,6 +667,12 @@ предложить проект
+ {% else %} + {% if answer.author|class_name == 'User' %} + Перейти к обсуждению + {% elif answer.author|class_name == 'Team'%} + Перейти к обсуждению + {% endif %} {% endif %}
@@ -843,6 +861,12 @@ предложить проект
+ {% else %} + {% if answer.author|class_name == 'User' %} + Перейти к обсуждению + {% elif answer.author|class_name == 'Team'%} + Перейти к обсуждению + {% endif %} {% endif %}
@@ -1016,6 +1040,12 @@ Восстановить
+ + {% if answer.author|class_name == 'User' %} + Перейти к обсуждению + {% elif answer.author|class_name == 'Team'%} + Перейти к обсуждению + {% endif %}
@@ -1083,9 +1113,10 @@ {% block js_block %} {% endblock %}