diff --git a/apps/map/forms.py b/apps/map/forms.py index 44b8351..841f59b 100644 --- a/apps/map/forms.py +++ b/apps/map/forms.py @@ -1,7 +1,9 @@ from django.urls import reverse +from django import forms +from django.utils.translation import ugettext as _ from crispy_forms.helper import FormHelper -from crispy_forms.layout import Submit, Layout -from crispy_forms.bootstrap import Tab, TabHolder +from crispy_forms.layout import Submit, Layout, HTML, Fieldset +from crispy_forms.bootstrap import Tab, TabHolder, PrependedText, FormActions from leaflet.forms.widgets import LeafletWidget from moderation.forms import BaseModeratedObjectForm @@ -19,12 +21,16 @@ class BaseCaseStudyForm(BaseModeratedObjectForm): self.helper.form_action = 'add' self.helper.label_class = 'col-lg-2' self.helper.field_class = 'col-lg-8' - self.helper.add_input(Submit('submit', 'Submit')) class Meta: model = CaseStudy fields = '__all__' - widgets = {'location': LeafletWidget(attrs={})} + widgets = { + 'location': LeafletWidget(attrs={}), + 'official_project_documents': forms.ClearableFileInput(attrs={'multiple': True}), + 'other_documents': forms.ClearableFileInput(attrs={'multiple': True}), + 'shapefiles': forms.ClearableFileInput(attrs={'multiple': True}), + } class ShortCaseStudyForm(BaseCaseStudyForm): @@ -69,7 +75,7 @@ class LongCaseStudyForm(BaseCaseStudyForm): self.helper.form_action = reverse('long-form') self.helper.layout = Layout( TabHolder( - Tab("First Page", + Tab(_("Basic information"), 'entry_name', 'location', 'sector_of_economy', @@ -86,28 +92,116 @@ class LongCaseStudyForm(BaseCaseStudyForm): 'project_status', 'synopsis', 'full_description', + 'project_owners', + 'shareholders', + 'financial_institutions', + 'energy_customers', 'image', 'image_caption', 'image_credit', 'video', + 'video_caption', + 'video_credit', 'media_coverage_mainstream', 'media_coverage_independent', - 'community_voices'), + 'community_voices', + 'direct_comms', + 'social_media_links', + FormActions( + HTML(""+_("Next")+"") + ) + ), Tab( - "Second Page", - 'generation_technology', - 'biomass_detail', - 'generation_technology_other', - 'total_generation_capacity', - 'total_investment', - 'technical_or_economic_details', - 'power_technology', - 'power_technology_other', - 'energy_storage_capacity', + _("Technical and economic analysis"), + Fieldset( + _("Power Generation Questions"), + 'generation_technology', + 'biomass_detail', + 'generation_technology_other', + 'total_generation_capacity', + 'generation_equipment_supplier', + 'total_investment', + 'technical_or_economic_details', + css_id="power_generation_questions" + ), + Fieldset( + _("Power Grids/Energy Storage Questions"), + 'power_technology', + 'power_technology_other', + 'energy_storage_capacity', + 'maximum_power_output', + 'discharge_time', + 'contractor_or_supplier_of_technology', + 'approximate_total_investment', + 'additional_technical_details', + css_id="power_grids_energy_storage_questions" + ), + Fieldset( + _("Mineral/Commodity Questions"), + '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" + ), + FormActions( + HTML(""+_("Previous")+""), + HTML(""+_("Next")+"") + ) + ), + Tab( + _("Socio-environmental analysis"), + Fieldset( + _("Positive Case Questions"), + 'positive_case_type', + 'socioeconomic_benefits', + 'project_status_detail', + 'obstacles_and_hindrances', + 'identified_partnerships', + css_id="positive_case_questions" + ), + Fieldset( + _("Negative Case Questions"), + 'negative_case_reasons', + 'negative_case_reasons_other', + 'negative_socioenvironmental_impacts', + 'isolated_or_widespread', + 'when_did_organising_start', + 'who_has_been_involved', + 'participation_mechanisms', + 'potential_partnerships', + 'wants_conversation_with_ojuso', + css_id="negative_case_questions" + ), + Fieldset( + _("Common Questions"), + 'key_actors_involved', + css_id="common_questions" + ), + FormActions( + HTML(""+_("Previous")+""), + HTML(""+_("Next")+"") + ) + ), + Tab( + _("Uploads"), + 'official_project_documents', + 'other_documents', + 'shapefiles', + 'coordinate_reference_system', + 'name_of_territory_or_area', + 'shown_on_other_platforms', + 'shown_on_other_platforms_detail', + FormActions( + HTML(""+_("Previous")+""), + Submit('submit', _('Submit'), css_class="btn-success pull-right") + ) ))) - - - class Meta(BaseCaseStudyForm.Meta): - fields = '__all__' \ No newline at end of file + fields = '__all__' diff --git a/apps/map/models.py b/apps/map/models.py index 9c294c2..6011c20 100644 --- a/apps/map/models.py +++ b/apps/map/models.py @@ -6,9 +6,16 @@ from django_extensions.db.fields import AutoSlugField from django_countries.fields import CountryField from django.utils.translation import ugettext as _ from django.template.defaultfilters import slugify +from multiselectfield import MultiSelectField from . import validators +class Shapefile(models.Model): + file = models.FileField( + upload_to='shapefiles/', + ) + + class CaseStudy(models.Model): """Model for case studies submitted to the Ojuso Platform""" @@ -88,6 +95,81 @@ class CaseStudy(models.Model): ('OT', _('Others')) ) + TYPE_OF_EXTRACTION_CHOICES = ( + ('SUR', _('Surface (open pit/open cast/open cut mining')), + ('SUB', _('Sub-surface (underground mining)')), + ('SEA', _('Seabed mining')), + ('URB', _('Urban mining/recycling')) + ) + + MINERAL_COMMODITY_CHOICES = ( + ('ALU', _('Aluminium (Bauxite)')), + ('ARS', _('Arsenic')), + ('BER', _('Beryllium')), + ('CAD', _('Cadmium')), + ('CHR', _('Chromium')), + ('COK', _('Coking')), + ('COA', _('Coal (for steel)')), + ('COP', _('Copper')), + ('GAL', _('Gallium')), + ('GER', _('Germanium')), + ('GLD', _('Gold')), + ('HRE', _('Heavy Rare Earth Elements (Gadolinium, Terbium, Dysprosium, Holmium, Erbium, Thulium, Ytterbium, Lutetium, Yttrium, Scandium)')), + ('IRN', _('Iron')), + ('LRE', _('Light Rare Earth Elements (Lanthanum, Cerium, Praseodymium, Neodymium, Promethium, Samarium, Europium)')), + ('LED', _('Lead')), + ('LIT', _('Lithium')), + ('MAN', _('Manganese')), + ('MER', _('Mercury')), + ('MOL', _('Molybdenum')), + ('NIC', _('Nickel')), + ('NIO', _('Niobium')), + ('PGM', _('Platinum group metals (ruthenium, rhodium, palladium, osmium, iridium, and platinum)')), + ('RHE', _('Rhenium')), + ('SIL', _('Silicon')), + ('SIV', _('Silver')), + ('TAN', _('Tantalum')), + ('TEL', _('Tellurium')), + ('THA', _('Thallium')), + ('TIN', _('Tin')), + ('TIT', _('Titanium')), + ('TUN', _('Tungsten')), + ('VAN', _('Vanadium')), + ('ZNC', _('Zinc')), + ('OTR', _('Other')) + ) + + USE_IN_ENERGY_ECONOMY_CHOICES = ( + ('WTM', _('Wind turbine manufacturing')), + ('SPM', _('Solar panel manufacturing')), + ('STM', _('Solar thermal system manufacturing')), + ('HGM', _('Hydropower generator manufacturing')), + ('GGM', _('Geothermal generator manufacturing')), + ('ESS', _('Energy storage (inc. battery systems)')), + ('OTR', _('Others')) + ) + + POSITIVE_CASE_TYPE_CHOICES = ( + ('CREP', _('Community renewable energy project')), + ('EACP', _('Energy as a commons project')), + ('PSEP', _('Public/state (federal, state, municipal) energy project')), + ('CORS', _('A case of responsible sourcing/supply chain/lifecycle management')), + ) + + NEGATIVE_CASE_REASONS_CHOICES = ( + ('VOLR', _('Violation of land rights')), + ('VOHR', _('Violation of fundamental human rights, indigenous rights and/or other collective rights')), + ('EIMP', _('Environmental impacts (severe impacts on ecosystems / violation of laws, plans or programs of \ + environmental conservation or territorial governance systems etc.')), + ('NCUL', _('Negative cultural impacts (erosion/destruction of bio-cultural heritage, impacts on sacred land \ + etc)')), + ('AGGR', _('Aggression/threats to community members opposed to the project, collaboration with organized crime \ + etc')), + ('ALAB', _('Abusive labour practices')), + ('CRUP', _('Corruption and/or irregular permitting or contracting, conflicts of interest etc')), + ('OTHR', _('Other reasons')) + ) + # Dynamically generate a list of choices 40 years prior and after the current year. YEAR_CHOICES = [(r, r) for r in range((datetime.datetime.now().year - 40), @@ -110,11 +192,10 @@ class CaseStudy(models.Model): date_created = models.DateTimeField(auto_now_add=True, null=False) # Slug derived from entry_name, used in urls for SEO - # TODO: Change this so it's not dynamic. Slugs should never change. - slug = AutoSlugField(populate_from=['entry_name']) + slug = AutoSlugField(populate_from=['entry_name'], editable=False) ## - # First Screen + # First Screen - Basic information ## # 1.1 @@ -193,13 +274,15 @@ class CaseStudy(models.Model): help_text=_("Select the most relevant type of ecosystem."), max_length=6, choices=TYPE_OF_ECOSYSTEM_CHOICES, + default=None, + null=True, + blank=True ) # 1.5.5.3 - describe_ecosystem = models.CharField( + describe_ecosystem = models.TextField( verbose_name=_("Describe the ecosystem"), help_text=_("In your own words, add more detail about the ecosystem."), - max_length=256, ) # 1.5.6 @@ -254,8 +337,7 @@ class CaseStudy(models.Model): verbose_name=_("Synopsis"), help_text=_("Briefly describe the project. This will be displayed at\ the top of the case study page. Maximum 500 chars (about \ - 3½ tweets)"), - max_length=500 + 3½ tweets)") ) # 1.10 @@ -398,9 +480,10 @@ class CaseStudy(models.Model): ) ## - # Second Screen + # Second Screen - Technical and economic analysis ## + # 2.1 - Renewable Energy Generation # 2.1.1 generation_technology = models.CharField( verbose_name=_("Generation technology"), @@ -415,7 +498,7 @@ class CaseStudy(models.Model): # 2.1.1.12 # Should be filled in if 2.1.1 was answered as biogas or biomass. biomass_detail = models.CharField( - verbose_name=_("Generation technology detail"), + verbose_name=_("Description of feedstock"), help_text=_("If you selected biogas or biomass, please describe the feedstock (where the fuel came from e.g. \ corn, algae, anaerobic digestion, commercial waste etc)"), max_length=200, @@ -443,7 +526,15 @@ class CaseStudy(models.Model): blank=True, ) - # 2.1.3 - autocomplete_light queryset + # 2.1.3 + # TODO: Auto-completion based on previous entries so we can query case-studies with the same answer. + generation_equipment_supplier = models.TextField( + verbose_name=_("Generation equipment supplier"), + help_text=_("Enter the supplier of the generation equipment. (E.g. Siemens)"), + default=None, + null=True, + blank=True + ) # 2.1.4 total_investment = models.IntegerField( @@ -464,7 +555,7 @@ class CaseStudy(models.Model): blank=True ) - # 2.2 - Only if 1.2.2 selected + # 2.2 - Power Grids / Energy Storage # 2.2.1 power_technology = models.CharField( verbose_name=_("Power technology"), @@ -476,6 +567,7 @@ class CaseStudy(models.Model): blank=True ) + # 2.2.1.4 power_technology_other = models.CharField( verbose_name=_("Other power technology"), help_text=_("If you answered 'others', please specify the power technologies."), @@ -485,6 +577,7 @@ class CaseStudy(models.Model): blank=True ) + # 2.2.2 energy_storage_capacity = models.IntegerField( verbose_name=_("Energy storage capacity"), help_text=_("Enter the total capacity of the energy storage system."), @@ -493,12 +586,321 @@ class CaseStudy(models.Model): blank=True ) - ## - # Third Screen - ## + # 2.2.2.1 + maximum_power_output = models.BigIntegerField( + verbose_name=_('Maximum power output'), + help_text=_('Enter the maximum power output of the storage system in Watts (W). (W=J/s)'), + default=None, + null=True, + blank=True + ) + + # 2.2.2.2 + discharge_time = models.BigIntegerField( + verbose_name=_('Time for discharge from full capacity'), + help_text=_('Enter the time it takes to discharge from full capacity at maximum power output (in seconds) \ + (1h=3600s)'), + default=None, + null=True, + blank=True + ) + + # 2.2.3 + contractor_or_supplier_of_technology = models.CharField( + verbose_name=_('Contractor and/or supplier of technology'), + help_text=_('List companies that act as contractors or suppliers of technology related to energy storage.'), + max_length=256, + default=None, + null=True, + blank=None + ) + + # 2.2.4 + approximate_total_investment = models.PositiveIntegerField( + verbose_name=_('Approximate total investment'), + help_text=_('Enter the approximate total investment in USD ($).'), + default=None, + null=True, + blank=None + ) + + # 2.2.5 + additional_technical_details = models.CharField( + verbose_name=_("Additional technical or economic details"), + help_text=_("Add any additional details such as: length, from-to, voltage, substations etc"), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 2.3.1.1 + minerals_or_commodities = models.CharField( + verbose_name=_("Mineral commodity/commodities"), + help_text=_("Select the mineral commodity that is primarily mined in this project"), + max_length=3, + choices=MINERAL_COMMODITY_CHOICES, + default=None, + null=True, + blank=True + ) + + # 2.3.1.2 + minerals_or_commodities_other = models.CharField( + verbose_name=_("Other mineral commodity"), + help_text=_("Enter the mineral commodity that isn't in the list."), + max_length=64, + default=None, + null=True, + blank=True + ) + + # 2.3.2.1 + use_in_energy_economy = models.CharField( + verbose_name=_("Potential user in renewable energy economy"), + help_text=_("Select the potential use of the minerals in the renewable energy economy"), + max_length=3, + choices=USE_IN_ENERGY_ECONOMY_CHOICES, + default=None, + null=True, + blank=True + ) + + # 2.3.2.9 + use_in_energy_economy_other = models.CharField( + verbose_name=_('Other use in energy economy'), + max_length=128, + default=None, + null=True, + blank=True + ) + + # 2.3.3.1 + project_life_span = models.CharField( + verbose_name=_("Project life span"), + help_text=_("e.g. 12 years of production, 15 years overall"), + max_length=200, + default=None, + null=True, + blank=None + ) + + # 2.3.3.2 + size_of_concessions = models.CharField( + verbose_name=_("Size of concessions"), + help_text=_("Describe the size of concession(s) granted to company/companies (e.g. 'one concession encompassing\ + 2,300 hectares')"), + max_length=200, + default=None, + null=True, + blank=None + ) + + # 2.3.3.3 + projected_production_of_commodities = models.CharField( + verbose_name=_("Projected production of key commodities"), + help_text=_("Describe the projected production of commodities per annum and overall (e.g. '40 million tonnes of\ + iron ore per year, 200 million tonnes over 5 year life of mine'"), + max_length=256, + default=None, + null=True, + blank=None + ) + + # 2.3.4 + type_of_extraction = models.CharField( + verbose_name=_("Type of extraction"), + max_length=2, + choices=TYPE_OF_EXTRACTION_CHOICES, + default=None, + null=True, + blank=True + ) + + # 2.3.5 + associated_infrastructure = models.CharField( + verbose_name=_("Associated infrastructure in the locality"), + help_text=_("List any associated infrastructure in the locality (e.g. tailings dams/mine waste storage and \ + treatment facilities; ore processing facilities; smelting facilities; hydroelectric dams/energy infrastructure;\ + transport infrastructure e.g. roads or rail."), + max_length=256, + default=None, + null=True, + blank=True + ) ## - # Fourth Screen + # Third Screen - Socio-economic analysis + ## + + # 3.1.1 + positive_case_type = models.CharField( + verbose_name=_('What kind of positive case is this entry about?'), + help_text=_('Select the most relevant type of positive case'), + choices=POSITIVE_CASE_TYPE_CHOICES, + max_length=4, + default=None, + null=True, + blank=True, + ) + + # 3.1.2 + socioeconomic_benefits = models.TextField( + verbose_name=_('Socio-economic benefits'), + help_text=_('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'), + default=None, + null=True, + blank=True + ) + + # 3.1.3 + 3.2.5 + key_actors_involved = models.CharField( + verbose_name=_('Key actors involved (individual/organisational)'), + max_length=256, + default=None, + null=True, + blank=True + ) + + # 3.1.4 + project_status_detail = models.TextField( + verbose_name=_('Current status of the project'), + help_text=_("Describe the current status of the project, expanding beyond 'existing', 'under construction' etc"), + default=None, + null=True, + blank=True + ) + + # 3.1.5 + obstacles_and_hindrances = models.CharField( + verbose_name=_('Obstacles and hindrances'), + help_text=_('List any obstacles or hindrances experienced in the course of the project'), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 3.1.6 + identified_partnerships = models.CharField( + verbose_name=_('Identified partnerships'), + help_text=_('Are you looking for partnerships or have any clearly identified need? If so, please describe it \ + here.'), + max_length=256, + default=None, + null=True, + blank=True + ) + + # 3.1.7.1 + 3.2.8.1 + + # 3.1.7.2 + 3.2.8.1 + + # 3.1.7.3 + 3.2.8.1 + + # 3.1.7.4 + 3.2.8.1 + + # 3.1.7.5 + 3.2.8.1 + + # 3.1.7.6 + 3.2.8.1 + + # 3.2.1 + negative_case_reasons = MultiSelectField( + choices=NEGATIVE_CASE_REASONS_CHOICES, + default=None, + null=True, + blank=True + ) + + # 3.2.1.9 + negative_case_reasons_other = models.CharField( + verbose_name=_("Other reason for negative case"), + help_text=_("Please include other reasons, noting that we aim to focus on projects with substantive negative \ + impacts on vulnerable groups."), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 3.2.2 + negative_socioenvironmental_impacts = models.TextField( + verbose_name=_("Describe the negative socio-environmental impacts"), + help_text=_("Provide a detailed description of the negative socio-environmental impacts (please provide all \ + relevant details, such as type of ecosystem and presence of any existing reserve in the area, \ + , specific communities affected by the project, total geographic footprint of the project, and \ + tenure system affected in the case of land grabs, kind of permits that were irregularly issued if \ + this is the case."), + default=None, + null=True, + blank=True + ) + + # 3.2.3 + isolated_or_widespread = models.TextField( + verbose_name=_("Describe if the project is isolated or commonplace."), + help_text=_("Is this an isolated project or are there similar projects in the same geographic area? If there \ + are more, can you describe them? Are there any significant cumulative synergistic effects?"), + default=None, + null=True, + blank=True + ) + + # 3.2.4.1 + when_did_organising_start = models.CharField( + verbose_name=_("When did local organising efforts begin?"), + help_text=_("Before the project started? During project implementation? After project implementation? \ + Describe in your own words."), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 3.2.4.2 + who_has_been_involved = models.CharField( + verbose_name=_("Which communities, groups and organisations have been involved?"), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 3.2.4.3 + participation_mechanisms = models.CharField( + verbose_name=_("What mechanisms of participation have been used?"), + help_text=_("e.g. direct action, local referendums, legal cases, letters or petitions etc"), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 3.2.6 + potential_partnerships = models.CharField( + verbose_name=_("Describe potential partnerships"), + help_text=_("Are you looking for partnerships or do you have any clearly identified need? If so, please \ + describe it here."), + max_length=512, + default=None, + null=True, + blank=True + ) + + # 3.2.7 + wants_conversation_with_ojuso = models.NullBooleanField( + verbose_name=_("Would you like to have a conversation with the ojuso team?"), + help_text=_("This would be a conversation about challenging or engaging related developers, companies and \ + investors."), + default=None, + null=True, + blank=True + ) + + ## + # Fourth Screen - Uploads ## # 4.1 @@ -507,7 +909,7 @@ class CaseStudy(models.Model): help_text=_("Attach any legal or official documents that relate to the project."), default=None, null=True, - blank=True + blank=True, ) # 4.2 @@ -516,13 +918,33 @@ class CaseStudy(models.Model): help_text=_("Attach any other documents that relate to the project."), default=None, null=True, + blank=True, + ) + + # 4.3.1 + shapefiles = models.FileField( + verbose_name=_("Shapefiles"), + help_text=_("If you have territory that you would like to show in relation to this project - e.g. Bienes \ + Comunales de Ixtepec etc. This is a set of 3 or more (often 5-6) files with file extensions like \ + .cpg, .dbf, .prj, .qpj, .shp, .shx"), + default=None, + null=True, blank=True ) - # 4.3 - definition_of_affected_territories = models.CharField( - verbose_name=_("Definition of affected territories"), - help_text=_("In your own words, define the territories that the project will affect."), + # 4.3.2 + coordinate_reference_system = models.CharField( + verbose_name=_("Coordinate reference system"), + help_text=_("Enter the coordinate reference system of the shapefiles."), + max_length=12, + default=None, + null=True, + blank=True + ) + + # 4.3.3 + name_of_territory_or_area = models.CharField( + verbose_name=_("Name of territory or area"), max_length=512, default=None, null=True, @@ -567,3 +989,6 @@ class CaseStudy(models.Model): def get_video_id(self): """Gets the 11 character YouTube video ID from the video field.""" return parse.parse_qs(parse.urlparse(self.video).query)["v"][0] + + + diff --git a/apps/map/static/map/images/ojuso-logo-black.png b/apps/map/static/map/images/ojuso-logo-black.png deleted file mode 100644 index b4ac255..0000000 Binary files a/apps/map/static/map/images/ojuso-logo-black.png and /dev/null differ diff --git a/apps/map/static/map/images/ojuso-logo-white.png b/apps/map/static/map/images/ojuso-logo-white.png deleted file mode 100644 index 0276cb1..0000000 Binary files a/apps/map/static/map/images/ojuso-logo-white.png and /dev/null differ diff --git a/apps/map/templates/map/detail.html b/apps/map/templates/map/detail.html index 6122759..28e0942 100644 --- a/apps/map/templates/map/detail.html +++ b/apps/map/templates/map/detail.html @@ -17,20 +17,20 @@
- {% trans "Back to Map" %} +

{{case_study.entry_name}}

{{case_study.synopsis}}

- {{case_study.get_sector_of_economy_display}} + {{case_study.get_sector_of_economy_display}} {% if case_study.positive_or_negative == "P" %} - {{case_study.get_positive_or_negative_display}} + {{case_study.get_positive_or_negative_display}} {% elif case_study.positive_or_negative == "N"%} - {{case_study.get_positive_or_negative_display}} + {{case_study.get_positive_or_negative_display}} {% endif %} - {{case_study.country.name}} + {{case_study.country.name}}
Created {{case_study.date_created|naturaltime}} by {{case_study.author}}
diff --git a/apps/map/templates/map/form.html b/apps/map/templates/map/form.html index 74268df..852b9b4 100644 --- a/apps/map/templates/map/form.html +++ b/apps/map/templates/map/form.html @@ -34,27 +34,67 @@ - + + + + {# Additional Stylesheets #} {% block stylesheets %} {% endblock %} - - + -