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",)