* Take the opportunity to reformat the source to not have so many hugely long lines. * Put a few things through gettext that weren't going through it before * Move 'Hold down Ctrl to select multiple files at once.' text to widget, out of help text for each individual control.
465 lines
17 KiB
Python
465 lines
17 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
|
|
|
|
|
|
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('<b>%s</b><br><span class="text-muted">%s</span>' %
|
|
(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
|
|
|
|
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'))
|
|
|
|
# Duplicate code from long form, below...
|
|
self.fields['sector_of_economy'] = forms.ChoiceField(
|
|
widget=forms.RadioSelect(),
|
|
choices=add_explanatory_text(
|
|
CaseStudy.SECTOR_CHOICES,
|
|
SECTOR_HELP
|
|
),
|
|
required=False
|
|
)
|
|
|
|
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(
|
|
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(
|
|
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'] = forms.ChoiceField(
|
|
widget=forms.RadioSelect(),
|
|
choices=add_explanatory_text(
|
|
CaseStudy.SECTOR_CHOICES,
|
|
SECTOR_HELP
|
|
),
|
|
required=False
|
|
)
|
|
|
|
self.fields['power_technology'] = forms.ChoiceField(
|
|
widget=forms.RadioSelect(),
|
|
choices=add_explanatory_text(
|
|
CaseStudy.POWER_TECHNOLOGY_CHOICES,
|
|
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.'
|
|
' 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.') + \
|
|
'</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',
|
|
'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(
|
|
HTML("<a class='btn btn-primary btnNext pull-right'>"+_("Next")+"</a>")
|
|
)
|
|
),
|
|
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(
|
|
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',
|
|
Div(
|
|
HTML(
|
|
"<label class='col-md-3 control-label'>" +
|
|
_("What kind of case is this entry about?") +
|
|
"</label>"),
|
|
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(
|
|
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',
|
|
)
|