ojuso-map/apps/map/forms.py

430 lines
16 KiB
Python

from django import forms
from django.urls import reverse, reverse_lazy
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout, HTML, Fieldset, Div
from crispy_forms.bootstrap import Tab, TabHolder, PrependedText, FormActions
from dal import autocomplete
from leaflet.forms.widgets import LeafletWidget
from apps.files.models import File, ImageFile
from .models import CaseStudy, SpatialRefSys, PointOfInterest
from .widgets import JSONFileListWidget
class MinimumZoomWidget(LeafletWidget):
geometry_field_class = 'MinimumZoomField'
class PointOfInterest(forms.models.ModelForm):
def __init__(self, *args, **kwargs):
super(PointOfInterest, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_id = 'case-study-form'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
self.helper.form_action = 'add'
self.helper.label_class = 'col-lg-2'
self.helper.field_class = 'col-lg-10'
self.helper.include_media = False
self.helper.form_action = reverse('point-of-interest-form')
self.helper.add_input(Submit('submit', _('Submit'), css_class='btn-success center-block'))
class Meta:
model = PointOfInterest
widgets = {
'location': MinimumZoomWidget(attrs={
'settings_overrides': {
'SCALE': False
}
}),
}
fields = [
'title',
'location',
'synopsis',
'link',
]
class BaseCaseStudyForm(forms.models.ModelForm):
"""Base form class for the CaseStudy model."""
def __init__(self, *args, **kwargs):
super(BaseCaseStudyForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_id = 'case-study-form'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
self.helper.form_action = 'add'
self.helper.label_class = 'col-lg-2'
self.helper.field_class = 'col-lg-8'
self.helper.include_media = False
class Meta:
model = CaseStudy
fields = '__all__'
widgets = {
'location': MinimumZoomWidget(attrs={
'settings_overrides': {
'SCALE': False
}
}),
}
class ShortCaseStudyForm(BaseCaseStudyForm):
"""Short version of the CaseStudy form."""
def __init__(self, *args, **kwargs):
super(ShortCaseStudyForm, self).__init__(*args, **kwargs)
self.helper.form_action = reverse('short-form')
self.helper.add_input(Submit('submit', _('Submit'), css_class='btn-success center-block'))
class Meta(BaseCaseStudyForm.Meta):
fields = [
'entry_name',
'location',
'sector_of_economy',
'positive_or_negative',
'country',
'area_of_land',
'land_ownership',
'land_ownership_details',
'location_context',
'type_of_ecosystem',
'describe_ecosystem',
'affected_communities',
'project_status',
'synopsis',
'full_description',
'video',
'media_coverage_mainstream',
'media_coverage_independent',
'community_voices'
]
class BootstrapClearableFileInput(forms.ClearableFileInput):
template_name = 'map/forms/widgets/file.html'
class LongCaseStudyForm(BaseCaseStudyForm):
"""Long version of the CaseStudy form."""
images = forms.FileField(
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'images_files',
}), required=False
)
images_files = forms.ModelMultipleChoiceField(
queryset=ImageFile.objects.all(),
widget=JSONFileListWidget(),
required=False
)
official_project_documents = forms.FileField(
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'official_project_documents_files',
}), required=False
)
official_project_documents_files = forms.ModelMultipleChoiceField(
queryset=File.objects.all(),
widget=JSONFileListWidget(),
required=False
)
other_documents = forms.FileField(
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'other_documents_files',
}), required=False
)
other_documents_files = forms.ModelMultipleChoiceField(
queryset=File.objects.all(),
widget=JSONFileListWidget(),
required=False
)
shapefiles = forms.FileField(
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'shapefiles_files',
}), required=False
)
shapefiles_files = forms.ModelMultipleChoiceField(
queryset=File.objects.all(),
widget=JSONFileListWidget(),
required=False
)
coordinate_reference_system = forms.ModelChoiceField(
queryset=SpatialRefSys.objects.all(),
widget=autocomplete.ModelSelect2(url='srs-autocomplete'),
initial=4326,
)
SECTOR_HELP = {
'RN': _("including electricity, heat or combined heat and power generation"),
'PG': '',
'SM': _("including supply of minerals"),
'MA': '',
}
POWER_TECHNOLOGY_HELP = {
'PT': _('Lines, transformers, machinery etc.'),
'ES': _('Biological, chemical, electrical, electromagnetic, electrochemical, mechanical including gravitational potential, thermal etc.'),
'HN': _('District heating/cooling, etc.'),
'OT': '',
}
def add_explanatory_text(self, model_choices, explanatory_text):
return [
(
choice[0],
mark_safe('<b>%s</b><br><span class="text-muted">%s</span>' %
(choice[1], explanatory_text[choice[0]])
)
) for choice in model_choices
]
def __init__(self, *args, **kwargs):
super(LongCaseStudyForm, self).__init__(*args, **kwargs)
self.fields['positive_case_type'] = forms.ChoiceField(
widget=forms.RadioSelect(),
choices=CaseStudy.POSITIVE_CASE_TYPE_CHOICES,
required=False
)
self.fields['sector_of_economy'] = forms.ChoiceField(
widget=forms.RadioSelect(),
choices=self.add_explanatory_text(
CaseStudy.SECTOR_CHOICES,
self.SECTOR_HELP
),
required=False
)
self.fields['power_technology'] = forms.ChoiceField(
widget=forms.RadioSelect(),
choices=self.add_explanatory_text(
CaseStudy.POWER_TECHNOLOGY_CHOICES,
self.POWER_TECHNOLOGY_HELP
),
required=False
)
self.fields['project_owners'].required = True
self.fields['shareholders'].required = True
self.fields['socioeconomic_benefits'].label = \
'<span class="organising organising-vs">' + \
_('Socio-environmental impacts (negative and potentially positive)') + \
'</span>' + \
'<span class="organising organising-pro">' + \
_('Socio-environmental impacts (positive and potentially negative)') + \
'</span>' + \
'<span class="organising organising-none organising-idk">' + \
_('Socio-environmental impacts (positive and negative)') + \
'</span>'
self.fields['socioeconomic_benefits'].help_text = \
'<span class="organising organising-none organising-idk">' + \
_('Please expand on your response given in the full description on page one. \
We would expect benefits to go beyond emissions savings, paying rent for land, \
or complying with environmental or social legislation. Please include other \
reasons, noting that we aim to focus on projects with substantive impacts on \
vulnerable groups.') + \
'</span>' + \
'<span class="organising organising-vs">' + \
_('Please expand on your response given in the description. Note that we aim to \
focus on violation of land rights / human rights / collective rights, substantive \
negative impacts on vulnerable groups, aggression / threats / violence, \
severe environmental and/or cultural impacts, abusive labor practices, and \
corruption / governance issues, but feel free to cover any additional aspect \
that you consider relevant. Please also describe and analyze socio-environmental \
impacts that could be presented or considered as positive.') + \
'</span>' + \
'<span class="organising organising-pro">' + \
_('Please expand on your response given in the description. Please also describe \
and analyze socio-environmental impacts that could be considered as negative.') + \
'</span>'
self.helper.form_action = reverse('long-form')
self.helper.layout = Layout(
TabHolder(
Tab(_("Basic information"),
'entry_name',
'location',
'country',
'shapefiles',
'shapefiles_files',
'coordinate_reference_system',
'name_of_territory_or_area',
'area_of_land',
'land_ownership',
'land_ownership_details',
'location_context',
'type_of_ecosystem',
'describe_ecosystem',
'affected_communities',
'project_status',
'synopsis',
'full_description',
'images',
'images_files',
'video',
'video_caption',
'video_credit',
Fieldset(
_("Ownership and finance"),
'project_owners',
'consultants_contractors',
'shareholders',
'financial_institutions',
'financial_institutions_other',
'energy_customers'
),
Fieldset(
_("Media reports and other communications"),
'media_coverage_mainstream',
'media_coverage_independent',
'community_voices',
'direct_comms',
'social_media_links'
),
FormActions(
HTML("<a class='btn btn-primary btnNext pull-right'>"+_("Next")+"</a>")
)
),
Tab(
_("Technical and economic analysis"),
'sector_of_economy',
Fieldset(
'',
'generation_type',
'generation_technology',
'biomass_detail',
'generation_technology_other',
'total_generation_capacity',
'generation_equipment_supplier',
PrependedText('total_investment', 'USD$'),
'technical_or_economic_details',
css_id="power_generation_questions"
),
Fieldset(
'',
'power_technology',
'power_technology_other',
'energy_storage_capacity',
'energy_transmission_capacity',
'contractor_or_supplier_of_technology',
PrependedText('approximate_total_investment', 'USD$'),
'additional_technical_details',
css_id="power_grids_energy_storage_questions"
),
Fieldset(
'',
'minerals_or_commodities',
'minerals_or_commodities_other',
'use_in_energy_economy',
'use_in_energy_economy_other',
'project_life_span',
'size_of_concessions',
'projected_production_of_commodities',
'type_of_extraction',
'associated_infrastructure',
css_id="mineral_commodity_questions"
),
Fieldset(
'',
'manufacturing_type',
'manufacturing_description',
'manufacturing_related_tech',
'manufacturing_factors',
'manufacturing_factors_description',
'manufacturing_ownership',
css_id="manufacturing_questions"
),
FormActions(
HTML("<a class='btn btn-primary btnPrevious'>"+_("Previous")+"</a>"),
HTML("<a class='btn btn-primary btnNext pull-right'>"+_("Next")+"</a>")
)
),
Tab(
_("Socio-environmental analysis"),
HTML("<p>" + _("In the following, we expect the analysis to reflect the perspective of the organization(s) or person(s) describing the case.") + "</p>"),
'positive_or_negative',
HTML("<b>What kind of case is this entry about?</b>"),
'positive_case_type',
'negative_case_reasons',
'negative_case_reasons_other',
'socioeconomic_benefits',
'isolated_or_widespread',
'key_actors_involved',
'project_status_detail',
'obstacles_and_hindrances',
'negative_socioenvironmental_impacts',
'when_did_organising_start',
'who_has_been_involved',
'participation_mechanisms',
'identified_partnerships',
'potential_partnerships',
'wants_conversation_with_ojuso',
Div(
css_id="common_questions"
),
FormActions(
HTML("<a class='btn btn-primary btnPrevious'>"+_("Previous")+"</a>"),
HTML("<a class='btn btn-primary btnNext pull-right'>"+_("Next")+"</a>")
)
),
Tab(
_("Contact details"),
'contact_email',
'contact_phone',
'contact_website',
PrependedText('contact_twitter', '@', placeholder='username'),
'contact_facebook',
'contact_other',
'shown_on_other_platforms',
'shown_on_other_platforms_detail',
FormActions(
HTML("<a class='btn btn-primary btnPrevious'>"+_("Previous")+"</a>"),
HTML("<a class='btn btn-primary btnNext pull-right'>"+_("Next")+"</a>")
)
),
Tab(
_("Uploads"),
'official_project_documents',
'official_project_documents_files',
'other_documents',
'other_documents_files',
FormActions(
HTML("<a class='btn btn-primary btnPrevious'>"+_("Previous")+"</a>"),
Submit('submit', _('Submit'), css_class="btn-success pull-right")
)
)))
class Meta(BaseCaseStudyForm.Meta):
exclude = ('approved',)
class Media:
js = (
'files/upload.js',
)