From 5cff5daf60a485ccb98a562faa113abf1b141722 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Mon, 11 Jul 2016 20:31:34 +0300 Subject: [PATCH] #ARC-13 --- .../management/commands/generate_projects.py | 2 +- archilance/mixins.py | 3 + archilance/settings/base.py | 1 + assets/index.js | 129 ++++----- .../{inspect.html => inspect_.html} | 0 common/templatetags/common_tags.py | 12 +- projects/forms.py | 62 ++++- .../templates/customer_project_create.html | 26 +- projects/templates/project_filter.html | 259 ++++++++++++++++++ projects/templates/project_list.html | 179 ------------ projects/urls.py | 8 +- projects/views.py | 84 +++++- templates/partials/base.html | 4 +- templates/partials/header.html | 4 +- 14 files changed, 488 insertions(+), 285 deletions(-) rename common/templates/templatetags/{inspect.html => inspect_.html} (100%) create mode 100644 projects/templates/project_filter.html delete mode 100644 projects/templates/project_list.html diff --git a/archilance/management/commands/generate_projects.py b/archilance/management/commands/generate_projects.py index 620c680..febb7cd 100644 --- a/archilance/management/commands/generate_projects.py +++ b/archilance/management/commands/generate_projects.py @@ -47,7 +47,7 @@ class Command(BaseCommand): # ('id', 'Relation? False', 'Null? False', 'Blank? True', 'Hidden? False'), # ('price_and_term_required', 'Relation? False', 'Null? False', 'Blank? True', 'Hidden? False'), # ('text', 'Relation? False', 'Null? False', 'Blank? True', 'Hidden? False'), - + diff --git a/archilance/mixins.py b/archilance/mixins.py index 35eef9a..a2645d2 100644 --- a/archilance/mixins.py +++ b/archilance/mixins.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.contrib.sites.models import Site from django.views.generic.base import ContextMixin @@ -16,6 +17,8 @@ class BaseMixin(ContextMixin): c['domain'] = Site.objects.get_current().domain + c['TEMPLATE_DEBUG'] = settings.TEMPLATE_DEBUG + return c diff --git a/archilance/settings/base.py b/archilance/settings/base.py index 8eeb4dc..96d7bd5 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -12,6 +12,7 @@ SECRET_KEY = 'vb6@b9zj7^f!^+x*e8=e!oundyu1!e*&0i(3gu2xwo4%fx4h&n' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +TEMPLATE_DEBUG = True # Show debug info in templates. See `projects/templates/project_filter.html` ALLOWED_HOSTS = [] diff --git a/assets/index.js b/assets/index.js index 896f1fa..acfb8c5 100644 --- a/assets/index.js +++ b/assets/index.js @@ -3,7 +3,7 @@ var $specSelects = $('.-spec-select') var specSelectOptions = { language: 'ru', //minimumInputLength: 1, // Commented out to immediately load remote data - placeholder: '', // Required by `allowClear` + placeholder: 'Выберите специализацию', // Required by `allowClear` allowClear: true, ajax: { @@ -52,8 +52,7 @@ if (chosenSpecId) updateSpecializationWidgets(chosenSpecId) $specSelects.on('change', function($evt) { - var specId = $evt.added.id - updateSpecializationWidgets(specId) + updateSpecializationWidgets($evt.added ? $evt.added.id : null) }) @@ -94,7 +93,7 @@ var $locationSelects = $('.-location-select') var locationSelectOptions = { language: 'ru', - placeholder: '', // Required by `allowClear` + placeholder: 'Выберите местоположение', // Required by `allowClear` allowClear: true, } @@ -119,8 +118,7 @@ getLocationTree(null).then(function(locs) { $locationSelects.on('change', function($evt) { - var locId = $evt.added.id - updateLocationWidgets(locId) + updateLocationWidgets($evt.added ? $evt.added.id : null) }) @@ -244,67 +242,70 @@ function getSpecializationTree(specId) { var specs = { specLevel1: null, specLevel2: null, specLevel3: null, specLevel4: null, } - - return $.ajax({url: '/api/specializations/' + specId + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - if (spec.level === 1) { - return _.merge(specs, {specLevel1: spec}) - } else if (spec.level === 2) { - var specLevel2 = spec - - return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - var specLevel1 = spec - - return _.merge(specs, { - specLevel1: specLevel1, - specLevel2: specLevel2, + if (specId === null) { + return $.when(specs) + } else { + return $.ajax({url: '/api/specializations/' + specId + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + if (spec.level === 1) { + return _.merge(specs, {specLevel1: spec}) + } else if (spec.level === 2) { + var specLevel2 = spec + + return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + var specLevel1 = spec + + return _.merge(specs, { + specLevel1: specLevel1, + specLevel2: specLevel2, + }) }) - }) - } else if (spec.level === 3) { - var specLevel3 = spec - - return $.ajax({url: '/api/specializations/' + specLevel3.parent.id + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - var specLevel2 = spec - - return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - var specLevel1 = spec - - return _.merge(specs, { - specLevel1: specLevel1, - specLevel2: specLevel2, - specLevel3: specLevel3, + } else if (spec.level === 3) { + var specLevel3 = spec + + return $.ajax({url: '/api/specializations/' + specLevel3.parent.id + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + var specLevel2 = spec + + return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + var specLevel1 = spec + + return _.merge(specs, { + specLevel1: specLevel1, + specLevel2: specLevel2, + specLevel3: specLevel3, + }) }) - }) - }) - } else if (spec.level === 4) { - var specLevel4 = spec - - return $.ajax({url: '/api/specializations/' + specLevel4.parent.id + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - var specLevel3 = spec - - return $.ajax({url: '/api/specializations/' + specLevel3.parent.id + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - var specLevel2 = spec - - return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'}) - .then(function(spec) { - var specLevel1 = spec - - return _.merge(specs, { - specLevel1: specLevel1, - specLevel2: specLevel2, - specLevel3: specLevel3, - specLevel4: specLevel4, + }) + } else if (spec.level === 4) { + var specLevel4 = spec + + return $.ajax({url: '/api/specializations/' + specLevel4.parent.id + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + var specLevel3 = spec + + return $.ajax({url: '/api/specializations/' + specLevel3.parent.id + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + var specLevel2 = spec + + return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'}) + .then(function(spec) { + var specLevel1 = spec + + return _.merge(specs, { + specLevel1: specLevel1, + specLevel2: specLevel2, + specLevel3: specLevel3, + specLevel4: specLevel4, + }) }) - }) - }) - }) - } - }) + }) + }) + } + }) + } } diff --git a/common/templates/templatetags/inspect.html b/common/templates/templatetags/inspect_.html similarity index 100% rename from common/templates/templatetags/inspect.html rename to common/templates/templatetags/inspect_.html diff --git a/common/templatetags/common_tags.py b/common/templatetags/common_tags.py index 1f76ddd..502febf 100644 --- a/common/templatetags/common_tags.py +++ b/common/templatetags/common_tags.py @@ -5,14 +5,14 @@ import os register = template.Library() -@register.inclusion_tag('templatetags/inspect.html', takes_context=True) -def inspect(context, obj): - return {'obj': pformat(obj.__dict__)} +# @register.inclusion_tag('templatetags/inspect.html', takes_context=True) +# def inspect(context, obj): +# return {'obj': pformat(obj.__dict__)} -@register.inclusion_tag('templatetags/inspect.html', takes_context=True) -def inspect2(context, obj): - return {'obj': pformat(dir(obj))} +@register.filter('inspect') +def inspect(obj): + return pformat(obj.__dict__) @register.simple_tag diff --git a/projects/forms.py b/projects/forms.py index fa0b5b9..f17c2f8 100644 --- a/projects/forms.py +++ b/projects/forms.py @@ -2,6 +2,8 @@ from django import forms from django.db.models import Q from django.forms.models import inlineformset_factory from mptt.forms import TreeNodeChoiceField +from pprint import pprint, pformat +import itertools from .models import Project, ProjectFile, Portfolio, Answer, Realty, PortfolioPhoto, Stage, Specialization from common.models import Location @@ -11,8 +13,59 @@ from users.models import User # RealtyFormSet = inlineformset_factory(Project, Realty) -class ProjectsForm(forms.Form): - name = forms.CharField(max_length=255) +class ProjectFilterForm(forms.ModelForm): + class Meta: + model = Project + + fields = ( + 'cro', + 'work_type', + 'specialization', + ) + + widgets = { + 'work_type': forms.Select(attrs={'class': 'selectpicker'}), + } + + def __init__(self, *args, **kwargs): + self.request = kwargs.pop('request') + super().__init__(*args, **kwargs) + + self.fields['work_type'].choices = tuple(itertools.chain((('',''),), self.fields['work_type'].choices)) + self.fields['work_type'].required = False + self.fields['work_type'].initial = '' + + self.fields['specialization'].required = False + + self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() + + +class ProjectFilterRealtyForm(forms.ModelForm): + class Meta: + model = Realty + + fields = ( + 'building_classification', + 'construction_type', + 'location', + ) + + widgets = { + 'building_classification': forms.Select(attrs={'class': 'selectpicker'}), + 'construction_type': forms.Select(attrs={'class': 'selectpicker'}), + } + + def __init__(self, *args, **kwargs): + self.request = kwargs.pop('request') + super().__init__(*args, **kwargs) + + self.fields['building_classification'].empty_label = '' + self.fields['building_classification'].required = False + + self.fields['construction_type'].empty_label = '' + self.fields['construction_type'].required = False + + self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() class CustomerProjectEditForm(forms.ModelForm): @@ -52,9 +105,7 @@ class CustomerProjectEditForm(forms.ModelForm): super().__init__(*args, **kwargs) self.fields['realty'].empty_label = 'Создать новый' - self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() - self.fields['specialization'].widget.attrs = {'class': '-spec-select', 'style': 'width: 100%'} if self.instance.pk: self.fields['files'].queryset = self.instance.files @@ -168,3 +219,6 @@ class CustomerProjectDeleteForm(forms.Form): super().__init__(*args, **kwargs) self.fields['pk'].queryset = self.req.user.projects.filter(Q(state='active') | Q(state='trashed')) + + +# import code; code.interact(local=dict(globals(), **locals())) diff --git a/projects/templates/customer_project_create.html b/projects/templates/customer_project_create.html index 6452d41..b55e31c 100644 --- a/projects/templates/customer_project_create.html +++ b/projects/templates/customer_project_create.html @@ -83,19 +83,19 @@
- +
- +
- +
- +
@@ -253,30 +253,22 @@
- +
- +
- +
- - -

Требуется допуск СРО

+ +

Требуется допуск (СРО)

diff --git a/projects/templates/project_filter.html b/projects/templates/project_filter.html new file mode 100644 index 0000000..d188b44 --- /dev/null +++ b/projects/templates/project_filter.html @@ -0,0 +1,259 @@ +{% extends 'partials/base.html' %} + +{% load common_tags %} + +{% block content %} + {% include 'partials/header.html' %} + +
+
+
+

Биржа проектов

+
+ +
+
+
+
+ + +
+
Тип работы
+
+
+
+ {{ form.work_type }} +
+
+ + +
+
Специализации
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+ + +
+ + + + +
+
+

Расширенный поиск

+ +
+
+
+
+
+ + + + + + + + + +
+
+
Классификация здания
+
Вид строительства
+
+
+ +
+
+ {{ realty_form.building_classification }} +
+ +
+ {{ realty_form.construction_type }} +
+
+
+ + + + + +
+
+
Местоположение
+
+ +
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ +
+
+ +

Требуется допуск (СРО)

+
+
+
+
+
+ + + + + + + + +
+

{{ display_msg }}

+ +
+
+ + + + + + + + + + + + +
+ {% for proj in projects %} +
+
+

+ {{ proj }} +

+
    +
  • + Объект "{{ proj.realty.name }}" +
  • +
  • + 0 ответ от имени группы +
  • +
+

{{ proj.text }}

+ + {% if TEMPLATE_DEBUG %} +
{{ proj|inspect }}

Specialization: {{ proj.specialization }}
Realty location: {{ proj.realty.location }}
Constr. type: {{ proj.realty.construction_type }}
Build. classif.: {{ proj.realty.building_classification }}
+ {% endif %} + +
    +
  • {{ proj.created }}
  • +
  • 0
  • +
  • {{ proj.answers.count }}
  • +
  • {{ proj.user }}
  • +
+
+
+

+ {{ proj.budget }} +

+
    + {% if proj.secure_deal %} +
  • Безопасная сделка
  • + {% endif %} + +
  • + Стадия: "П" +
  • + +
  • + Отказаться и переместить + в корзину +
  • +
+
+
+ {% endfor %} +
+
+ {% include 'partials/pagination.html' %} +
+ + {% include 'partials/footer.html' %} +
+
+{% endblock %} diff --git a/projects/templates/project_list.html b/projects/templates/project_list.html deleted file mode 100644 index eaa26d0..0000000 --- a/projects/templates/project_list.html +++ /dev/null @@ -1,179 +0,0 @@ -{% extends 'partials/base.html' %} - -{% block content %} - {% include 'partials/header.html' %} - -
-
-
-

Биржа проектов

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

Расширенный поиск

- -
-
-
-
-
-
-
-
Классификация здания
-
Вид строительства
-
Местоположение
-
-
-
-
- -
-
- -
-
- -
-
- -
-
-
-
- -

Требуется допуск (СРО)

-
-
-
-
-
- -
- {% for proj in object_list %} -
-
-

- {{ proj }} -

-
    -
  • - Объект "{{ proj.realty.name }}" -
  • -
  • - 0 ответ от имени группы -
  • -
-

{{ proj.text }}

-
    -
  • {{ proj.created }}
  • -
  • 0
  • -
  • {{ proj.answers.count }}
  • -
  • {{ proj.user }}
  • -
-
-
-

- {{ proj.budget }} -

-
    - {% if proj.secure_deal %} -
  • Безопасная сделка
  • - {% endif %} - -
  • - Стадия: "П" -
  • - -
  • - Отказаться и переместить - в корзину -
  • -
-
-
- {% endfor %} -
-
- {% include 'partials/pagination.html' %} -
- - {% include 'partials/footer.html' %} -
-
-{% endblock %} diff --git a/projects/urls.py b/projects/urls.py index 7614498..4cc1dd4 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -3,6 +3,8 @@ from django.views.generic import TemplateView from .views import ( add_candidate, + contractor_portfolio_create, + ContractorPortfolioUpdateView, ContractorProjectAnswerView, CustomerProjectCreateView, CustomerProjectDeleteView, @@ -11,16 +13,14 @@ from .views import ( CustomerProjectTrashView, OfferOrderView, ProjectComparisonView, - ProjectsView, + ProjectFilterView, ProjectView, - contractor_portfolio_create, - ContractorPortfolioUpdateView, ) app_name = 'projects' urlpatterns = [ - urls.url(r'^$', ProjectsView.as_view(), name='list'), + urls.url(r'^$', ProjectFilterView.as_view(), name='project-filter'), urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'), urls.url(r'^(?P\d+)/$', ProjectView.as_view(), name='detail'), diff --git a/projects/views.py b/projects/views.py index 8f74ddf..c710fb0 100644 --- a/projects/views.py +++ b/projects/views.py @@ -17,19 +17,91 @@ from users.models import User from .forms import ( ContractorProjectAnswerForm, - CustomerProjectEditForm, - PortfolioForm, CustomerProjectDeleteForm, CustomerProjectEditForm, + CustomerProjectEditForm, CustomerProjectRestoreForm, CustomerProjectTrashForm, + PortfolioForm, + ProjectFilterForm, + ProjectFilterRealtyForm, RealtyForm, ) -class ProjectsView(ListView): - model = Project - template_name = 'project_list.html' +class ProjectFilterView(BaseMixin, View): + template_name = 'project_filter.html' + form_class = ProjectFilterForm + realty_form = ProjectFilterRealtyForm + + def get(self, request, *args, **kwargs): + form = self.form_class(request.GET, request=request) + realty_form = self.realty_form(request.GET, request=request, prefix='realty_form') + context = self.get_context_data(**_.merge({}, request.GET, kwargs)) + display_msg = 'Список проектов' + + projects = Project.objects + + if form.is_valid() and realty_form.is_valid(): + cro = form.cleaned_data.get('cro') + work_type = form.cleaned_data.get('work_type') + specialization = form.cleaned_data.get('specialization') + + building_classification = realty_form.cleaned_data.get('building_classification') + construction_type = realty_form.cleaned_data.get('construction_type') + location = realty_form.cleaned_data.get('location') + + projects = projects.filter(cro=cro) + + if work_type: projects = projects.filter(work_type=work_type) + + if specialization: + projects = projects.filter( + specialization__lft__gte=specialization.lft, + specialization__rght__lte=specialization.rght, + ) + + if building_classification: projects = projects.filter(realty__building_classification=building_classification) + if construction_type: projects = projects.filter(realty__construction_type=construction_type) + + if location: + projects = projects.filter( + realty__location__lft__gte=location.lft, + realty__location__rght__lte=location.rght, + ) + + project_count = projects.count() + display_msg = 'Найдено %s проектов' % project_count if project_count > 0 else 'Ничего не найдено' + else: + display_msg = 'Пожалуйста, введите корректные данные' + + if form.errors: + messages.info(request, ( + '

Произошла ошибка (form)

' + '
{form}
' + ).format(form=pformat(form.errors))) + + if realty_form and realty_form.errors: + messages.info(request, ( + '

Произошла ошибка (realty_form)

' + '
{realty_form}
' + ).format(realty_form=pformat(realty_form.errors))) + + order_by = request.GET.get('order_by') # TODO: Validate + + if order_by: + projects = projects.order_by(order_by) + + projects = projects[:10] + + context.update({ + 'form': form, + 'realty_form': realty_form, + 'projects': projects, + 'display_msg': display_msg, + }) + + return render(request, self.template_name, context) class ProjectView(BaseMixin, View): @@ -335,4 +407,6 @@ class ContractorPortfolioUpdateView(UpdateView): def get_success_url(self): return reverse('proje') + + # import code; code.interact(local=dict(globals(), **locals())) diff --git a/templates/partials/base.html b/templates/partials/base.html index 951b64f..12c8ad1 100644 --- a/templates/partials/base.html +++ b/templates/partials/base.html @@ -25,9 +25,7 @@ - - - {% endcompress %} +{% endcompress %} diff --git a/templates/partials/header.html b/templates/partials/header.html index 573a7ca..7e002a7 100644 --- a/templates/partials/header.html +++ b/templates/partials/header.html @@ -9,7 +9,7 @@