from crispy_forms.bootstrap import FormActions
from crispy_forms.bootstrap import PrependedText
from crispy_forms.bootstrap import Tab
from crispy_forms.bootstrap import TabHolder
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Div
from crispy_forms.layout import Fieldset
from crispy_forms.layout import HTML
from crispy_forms.layout import Layout
from crispy_forms.layout import Submit
from dal import autocomplete
from django import forms
from django.urls import reverse
from django.urls import reverse_lazy
from django.utils.safestring import mark_safe
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
from leaflet.forms.widgets import LeafletWidget
from .models import CaseStudy
from .models import PointOfInterest
from .models import SpatialRefSys
from .widgets import JSONFileListWidget
from apps.files.models import File
from apps.files.models import ImageFile
SECTOR_HELP = {
"RN": _("Including electricity, heat or combined heat and power generation"),
"PG": "",
"ST": _(
"Biological, chemical, electrical, electromagnetic, electrochemical,"
" mechanical including gravitational potential, thermal, etc."
),
"SM": _("Including supply of minerals"),
"MA": "",
}
POWER_TECHNOLOGY_HELP = {
"PT": _("Lines, transformers, machinery, etc."),
"HN": _("District heating/cooling, etc."),
"OT": "",
}
def add_explanatory_text(model_choices, explanatory_text):
return [
(
choice[0],
mark_safe(
'%s
%s'
% (choice[1], explanatory_text[choice[0]])
),
)
for choice in model_choices
]
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.label_class = "col-md-3"
self.helper.field_class = "col-md-9"
self.helper.include_media = False
# Parse number fields correctly for the locale
number_fields = [
"area_of_land",
"total_generation_capacity",
"total_investment",
"energy_storage_capacity",
"energy_transmission_capacity",
"area_of_land",
"total_generation_capacity",
"total_investment",
]
for field_name in number_fields:
if field_name in self.fields:
self.fields[field_name].localize = True
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.add_input(
Submit("submit", _("Submit"), css_class="btn-success center-block")
)
self.fields["sector_of_economy"].widget = forms.RadioSelect()
self.fields["sector_of_economy"].required = False
self.fields["sector_of_economy"].choices = add_explanatory_text(
CaseStudy.SECTOR_CHOICES, SECTOR_HELP
)
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"
def PreviousButton():
return HTML(
format_lazy(
"{prev}", prev=_("Previous")
)
)
def NextButton():
return HTML(
format_lazy(
"{next}", next=_("Next")
)
)
class LongCaseStudyForm(BaseCaseStudyForm):
"""Long version of the CaseStudy form."""
images = forms.FileField(
label=_("Images"),
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(
label=_("Official project documents"),
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(
label=_("Other documents"),
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(
label=CaseStudy.shapefiles_label,
help_text=CaseStudy.shapefiles_help_text,
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(
label=_("Coordinate reference system"),
queryset=SpatialRefSys.objects.all(),
widget=autocomplete.ModelSelect2(url="srs-autocomplete"),
initial=4326,
)
def __init__(self, *args, **kwargs):
super(LongCaseStudyForm, self).__init__(*args, **kwargs)
self.fields["positive_case_type"].label = ""
self.fields["negative_case_reasons"].label = ""
self.fields["sector_of_economy"].widget = forms.RadioSelect()
self.fields["sector_of_economy"].required = False
self.fields["sector_of_economy"].choices = add_explanatory_text(
CaseStudy.SECTOR_CHOICES, SECTOR_HELP
)
self.fields["power_technology"].widget = forms.RadioSelect()
self.fields["power_technology"].required = False
self.fields["power_technology"].choices = add_explanatory_text(
CaseStudy.POWER_TECHNOLOGY_CHOICES, POWER_TECHNOLOGY_HELP
)
self.fields["project_owners"].required = True
self.fields["shareholders"].required = True
organising_vs_label = _(
"Socio-environmental impacts (negative and potentially positive)"
)
organising_pro_label = _(
"Socio-environmental impacts (positive and potentially negative)"
)
organising_other_label = _(
"Socio-environmental impacts (positive and negative)"
)
self.fields["socioeconomic_benefits"].label = format_lazy(
(
'{vs}'
'{pro}'
'{other}'
),
vs=organising_vs_label,
pro=organising_pro_label,
other=organising_other_label,
)
organising_other_text = _(
"Please expand on your response given in the full description on page one."
" For example, for positive impacts you need to go beyond emissions"
" savings, paying rent for land, or complying with environmental or social"
" legislation. For negative impacts you need to focus on substantive"
" impacts on vulnerable groups, violations of land rights or abusive labour"
" practices."
)
organising_vs_text = _(
"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."
)
organising_pro_text = _(
"Please expand on your response given in the description. Please also"
" describe and analyze socio-environmental impacts that could be considered"
" as negative."
)
self.fields["socioeconomic_benefits"].help_text = format_lazy(
(
'{other}'
'{vs}'
'{pro}'
),
vs=organising_vs_text,
pro=organising_pro_text,
other=organising_other_text,
)
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",
"people_affected_other",
"project_status",
"start_year",
"completion_year",
"synopsis",
"full_description",
"images",
"images_files",
"video",
"video_caption",
"video_credit",
Fieldset(
_("Owners and financiers"),
"project_owners",
"consultants_contractors",
"shareholders",
"financial_institutions",
"financial_institutions_other",
),
Fieldset(
_("Media reports and other communications"),
"media_coverage_mainstream",
"media_coverage_independent",
"community_voices",
"direct_comms",
"social_media_links",
),
FormActions(NextButton()),
),
Tab(
_("Technical and economic analysis"),
"sector_of_economy",
Div(
"generation_type",
"generation_technology",
css_class="power_generation_questions",
),
Div("power_technology", css_class="energy_network_questions"),
Div(
"energy_details",
css_class="energy_generation_network_and_storage_questions",
),
Div(
"biomass_detail",
"total_generation_capacity",
css_class="power_generation_questions",
),
Div(
"energy_transmission_capacity",
css_class="energy_network_questions",
),
Div(
"energy_storage_capacity", css_class="energy_storage_questions"
),
Div(
PrependedText("total_investment", "USD $"),
"contractor_or_supplier_of_technology",
"energy_customers",
"additional_technical_details",
css_class="energy_generation_network_and_storage_questions",
),
Div(
"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_class="mineral_commodity_questions",
),
Div(
"manufacturing_type",
"manufacturing_description",
"manufacturing_related_tech",
"manufacturing_factors",
"manufacturing_factors_description",
"manufacturing_ownership",
css_class="manufacturing_questions",
),
FormActions(PreviousButton(), NextButton()),
),
Tab(
_("Socio-environmental analysis"),
HTML(
format_lazy(
"
{text}
", text=_( "In the following, we expect the analysis to reflect" " the perspective of the organization(s) or person(s)" " describing the case." ), ) ), "positive_or_negative", Div( HTML( format_lazy( "", text=_("What kind of case is this entry about?"), ) ), Div( "positive_case_type", "negative_case_reasons", css_class="col-md-9", ), css_class="form-group", ), "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", Div(css_class="common_questions"), FormActions(PreviousButton(), NextButton()), ), 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(PreviousButton(), NextButton()), ), Tab( _("Uploads"), "official_project_documents", "official_project_documents_files", "other_documents", "other_documents_files", FormActions( PreviousButton(), Submit( "submit", _("Submit"), css_class="btn-success pull-right" ), ), ), ) ) class Meta(BaseCaseStudyForm.Meta): exclude = ("approved",) class Media: js = ("files/upload.js",)