Add updated front end, updated CaseStudy model and profiles app

This commit is contained in:
Livvy Mackintosh 2017-10-31 14:57:26 +00:00
parent f91b4d2a2a
commit 43d6ec989b
30 changed files with 1065 additions and 77 deletions

View File

@ -1,13 +1,14 @@
from django import forms
from django.urls import reverse from django.urls import reverse
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit from crispy_forms.layout import Submit, Layout
from crispy_forms.bootstrap import Tab, TabHolder
from leaflet.forms.widgets import LeafletWidget from leaflet.forms.widgets import LeafletWidget
from moderation.forms import BaseModeratedObjectForm
from .models import CaseStudy from .models import CaseStudy
class BaseCaseStudyForm(forms.ModelForm): class BaseCaseStudyForm(BaseModeratedObjectForm):
"""Base form class for the CaseStudy model.""" """Base form class for the CaseStudy model."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(BaseCaseStudyForm, self).__init__(*args, **kwargs) super(BaseCaseStudyForm, self).__init__(*args, **kwargs)
@ -52,6 +53,11 @@ class ShortCaseStudyForm(BaseCaseStudyForm):
'synopsis', 'synopsis',
'full_description', 'full_description',
'image', 'image',
'image_caption',
'image_credit',
'video',
'media_coverage_mainstream',
'media_coverage_independent',
'community_voices' 'community_voices'
] ]
@ -61,6 +67,47 @@ class LongCaseStudyForm(BaseCaseStudyForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(LongCaseStudyForm, self).__init__(*args, **kwargs) super(LongCaseStudyForm, self).__init__(*args, **kwargs)
self.helper.form_action = reverse('long-form') self.helper.form_action = reverse('long-form')
self.helper.layout = Layout(
TabHolder(
Tab("First Page",
'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',
'affects_indigenous',
'affects_indigenous_detail',
'project_status',
'synopsis',
'full_description',
'image',
'image_caption',
'image_credit',
'video',
'media_coverage_mainstream',
'media_coverage_independent',
'community_voices'),
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',
)))
class Meta(BaseCaseStudyForm.Meta): class Meta(BaseCaseStudyForm.Meta):
fields = '__all__' fields = '__all__'

View File

@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-11 16:06
from __future__ import unicode_literals
import apps.map.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0009_auto_20171007_1544'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='completion_year',
field=models.IntegerField(blank=True, choices=[(1977, 1977), (1978, 1978), (1979, 1979), (1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024), (2025, 2025), (2026, 2026), (2027, 2027), (2028, 2028), (2029, 2029), (2030, 2030), (2031, 2031), (2032, 2032), (2033, 2033), (2034, 2034), (2035, 2035), (2036, 2036), (2037, 2037), (2038, 2038), (2039, 2039), (2040, 2040), (2041, 2041), (2042, 2042), (2043, 2043), (2044, 2044), (2045, 2045), (2046, 2046), (2047, 2047), (2048, 2048), (2049, 2049), (2050, 2050), (2051, 2051), (2052, 2052), (2053, 2053), (2054, 2054), (2055, 2055), (2056, 2056), (2057, 2057)], default=None, help_text="Select the year the project was completed. If the project hasn't finished, select the projected completion year.", null=True, verbose_name='Completion year'),
),
migrations.AddField(
model_name='casestudy',
name='direct_comms',
field=models.TextField(default=None, help_text='Add any reports of direct communication between community members and representatives of developers/companies/investors.', max_length=500, null=True, verbose_name='Reports of direct communications'),
),
migrations.AddField(
model_name='casestudy',
name='energy_customers',
field=models.CharField(blank=True, default=None, help_text="List any wholesale energy customers that take energy from the development. E.g. 'national grids' or private energy suppliers.", max_length=120, null=True, verbose_name='Energy consumers'),
),
migrations.AddField(
model_name='casestudy',
name='financial_institutions',
field=models.CharField(blank=True, default=None, help_text='List banks and other financial institutions that have or are considering extending loans or guarantees to the project. Separate with a comma.', max_length=120, null=True, verbose_name='Financial institutions'),
),
migrations.AddField(
model_name='casestudy',
name='image_caption',
field=models.CharField(default=None, max_length=500, null=True, verbose_name='Image caption'),
),
migrations.AddField(
model_name='casestudy',
name='image_credit',
field=models.CharField(default=None, max_length=200, null=True, verbose_name='Image credit(s)'),
),
migrations.AddField(
model_name='casestudy',
name='media_coverage_independent',
field=models.TextField(default=None, help_text='Provide any links to grassroots/independent media coverage.', max_length=500, null=True, verbose_name='Independent grassroots reports'),
),
migrations.AddField(
model_name='casestudy',
name='media_coverage_mainstream',
field=models.TextField(default=None, help_text='Provide any links to mainstream media coverage.', max_length=500, null=True, verbose_name='Links to media reports'),
),
migrations.AddField(
model_name='casestudy',
name='project_owners',
field=models.CharField(blank=True, default=None, help_text='List companies or organisations that own the project and/or facilities. Separate with a comma.', max_length=120, null=True, verbose_name='Project and facility owners'),
),
migrations.AddField(
model_name='casestudy',
name='shareholders',
field=models.CharField(blank=True, default=None, help_text="List shareholders of the project owners you've just listed. Separate with a comma.", max_length=120, null=True, verbose_name='Shareholders of the project owners'),
),
migrations.AddField(
model_name='casestudy',
name='social_media_links',
field=models.TextField(blank=True, default=None, help_text='Add any links to social media accounts directly relating to the project.', max_length=500, null=True, verbose_name='Social media links'),
),
migrations.AddField(
model_name='casestudy',
name='start_year',
field=models.IntegerField(blank=True, choices=[(1977, 1977), (1978, 1978), (1979, 1979), (1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024), (2025, 2025), (2026, 2026), (2027, 2027), (2028, 2028), (2029, 2029), (2030, 2030), (2031, 2031), (2032, 2032), (2033, 2033), (2034, 2034), (2035, 2035), (2036, 2036), (2037, 2037), (2038, 2038), (2039, 2039), (2040, 2040), (2041, 2041), (2042, 2042), (2043, 2043), (2044, 2044), (2045, 2045), (2046, 2046), (2047, 2047), (2048, 2048), (2049, 2049), (2050, 2050), (2051, 2051), (2052, 2052), (2053, 2053), (2054, 2054), (2055, 2055), (2056, 2056), (2057, 2057)], default=None, help_text="Select the year the project was started. If the project hasn't begun, select the projected start year.", null=True, verbose_name='Start year'),
),
migrations.AddField(
model_name='casestudy',
name='video_caption',
field=models.CharField(default=None, max_length=500, null=True, verbose_name='Video caption'),
),
migrations.AddField(
model_name='casestudy',
name='video_credit',
field=models.CharField(default=None, max_length=500, null=True, verbose_name='Video credit(s)'),
),
migrations.AlterField(
model_name='casestudy',
name='affects_indigenous',
field=models.BooleanField(help_text='Does the project affect indigenous communities?', verbose_name='Affects indigenous people?'),
),
migrations.AlterField(
model_name='casestudy',
name='community_voices',
field=models.TextField(help_text='Add any direct quotes from members of the community that relate to this project', verbose_name='Community Voices'),
),
migrations.AlterField(
model_name='casestudy',
name='date_created',
field=models.DateTimeField(auto_now_add=True),
),
migrations.AlterField(
model_name='casestudy',
name='land_ownership_details',
field=models.CharField(blank=True, help_text="Please specify details about land ownership if you chose 'other'", max_length=256, null=True, verbose_name='Land ownership details'),
),
migrations.AlterField(
model_name='casestudy',
name='video',
field=models.URLField(help_text='Copy the URL to a related YouTube™ video that relates to the case study.', max_length=43, validators=[apps.map.validators.YoutubeURLValidator()], verbose_name='YouTube Video'),
),
]

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-12 15:52
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0010_auto_20171011_1606'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='generation_technology',
field=models.CharField(blank=True, choices=[('SSWE', 'Small-scale wind energy (less than 500kW)'), ('LSWE', 'Large-scale wind energy (more than 500kW)'), ('SSPV', 'Small-scale photovoltaic electricity (less than 500kW)'), ('LSPV', 'Large-scale photovoltaic electricity (more than 500kW)'), ('STHE', 'Solar thermal electricity (e.g using parabolic reflectors)'), ('SHYD', 'Small hydroelectric (less than 1MW)'), ('MHYD', 'Medium hydroelectric (between 1-20MW)'), ('LHYD', 'Large hydroelectric (more than 20MW - often not considered renewable)'), ('GEOT', 'Geothermal electricity'), ('BIOG', 'Biogas turbine'), ('OTHB', 'Other biomass (including liquid/solid biofuel)')], default=None, help_text='Select the type of renewable energy generation that most applies to this case study.', max_length=4, null=True, verbose_name='Generation technology'),
),
]

View File

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-12 16:10
from __future__ import unicode_literals
import django.contrib.gis.db.models.fields
from django.db import migrations, models
import django_countries.fields
class Migration(migrations.Migration):
dependencies = [
('map', '0011_casestudy_generation_technology'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='biomass_detail',
field=models.CharField(blank=True, default=None, 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, null=True, verbose_name='Generation technology detail'),
),
migrations.AddField(
model_name='casestudy',
name='generation_technology_other',
field=models.CharField(blank=True, default=None, help_text='If you selected other, please specify the generation technology (e.g. tidal, wave etc)', max_length=200, null=True, verbose_name='Other generation type'),
),
migrations.AddField(
model_name='casestudy',
name='total_generation_capacity',
field=models.IntegerField(blank=True, default=None, help_text='Please enter the total generation capacity of the project in kW', null=True, verbose_name='Total generation capacity (in kW)'),
),
migrations.AlterField(
model_name='casestudy',
name='country',
field=django_countries.fields.CountryField(help_text='Select the country of the project', max_length=2, verbose_name='Country field'),
),
migrations.AlterField(
model_name='casestudy',
name='generation_technology',
field=models.CharField(blank=True, choices=[('SSWE', 'Small-scale wind energy (less than 500kW)'), ('LSWE', 'Large-scale wind energy (more than 500kW)'), ('SSPV', 'Small-scale photovoltaic electricity (less than 500kW)'), ('LSPV', 'Large-scale photovoltaic electricity (more than 500kW)'), ('STHE', 'Solar thermal electricity (e.g using parabolic reflectors)'), ('SHYD', 'Small hydroelectric (less than 1MW)'), ('MHYD', 'Medium hydroelectric (between 1-20MW)'), ('LHYD', 'Large hydroelectric (more than 20MW - often not considered renewable)'), ('GEOT', 'Geothermal electricity'), ('BIOG', 'Biogas turbine'), ('OTHB', 'Other biomass (including liquid/solid biofuel)'), ('OTHR', 'Other (tidal, wave etc)')], default=None, help_text='Select the type of renewable energy generation that most applies to this case study.', max_length=4, null=True, verbose_name='Generation technology'),
),
migrations.AlterField(
model_name='casestudy',
name='location',
field=django.contrib.gis.db.models.fields.PointField(help_text='Place a marker using the tools on the left of the map. Zoom in as far as you can so the placement is accurate (important)', srid=4326, verbose_name='Project location'),
),
]

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-12 16:40
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0012_auto_20171012_1610'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='technical_or_economic_details',
field=models.CharField(blank=True, default=None, help_text='Specify any additional technical or economic details relating to the project.', max_length=500, null=True, verbose_name='Additional technical or economic details'),
),
migrations.AddField(
model_name='casestudy',
name='total_investment',
field=models.IntegerField(blank=True, default=None, help_text='The approximate total investment for the project in USD.', null=True, verbose_name='Total investment (in USD)'),
),
migrations.AlterField(
model_name='casestudy',
name='generation_technology',
field=models.CharField(blank=True, choices=[('Wind energy', (('SSWE', 'Small-scale (less than 500kW)'), ('LSWE', 'Large-scale (more than 500kW)'))), ('Photovoltaic electricity', (('SSPV', 'Small-scale (less than 500kW)'), ('LSPV', 'Large-scale (more than 500kW)'))), ('Hydroelectric', (('SHYD', 'Small-scale (less than 1MW)'), ('MHYD', 'Medium-scale (between 1-20MW)'), ('LHYD', 'Large-scale (more than 20MW - often not considered renewable)'))), ('STHE', 'Solar thermal electricity (e.g using parabolic reflectors)'), ('GEOT', 'Geothermal electricity'), ('BIOG', 'Biogas turbine'), ('OTHB', 'Other biomass (including liquid/solid biofuel)'), ('OTHR', 'Other (tidal, wave etc)')], default=None, help_text='Select the type of renewable energy generation that most applies to this case study.', max_length=4, null=True, verbose_name='Generation technology'),
),
migrations.AlterField(
model_name='casestudy',
name='total_generation_capacity',
field=models.PositiveIntegerField(blank=True, default=None, help_text='Please enter the total generation capacity of the project in kW', null=True, verbose_name='Total generation capacity (in kW)'),
),
]

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-25 20:35
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0013_auto_20171012_1640'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='power_technology',
field=models.CharField(blank=True, choices=[('PT', 'Power transmission (grid lines, substations etc)'), ('ES', 'Energy storage (pumped storage, compressed air, battery systems etc'), ('OT', 'Others')], default=None, help_text='Select the related energy technology.', max_length=2, null=True, verbose_name='Power technology'),
),
migrations.AddField(
model_name='casestudy',
name='power_technology_other',
field=models.CharField(blank=True, default=None, help_text="If you answered 'others', please specify the power technologies.", max_length=128, null=True, verbose_name='Other power technology'),
),
]

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-30 15:50
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0014_auto_20171025_2035'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='energy_storage_capacity',
field=models.IntegerField(blank=True, default=None, help_text='Enter the total capacity of the energy storage system.', null=True, verbose_name='Energy storage capacity'),
),
migrations.AlterField(
model_name='casestudy',
name='affects_indigenous_detail',
field=models.CharField(blank=True, default=None, help_text='What group of indigenous people does the community belong to?', max_length=256, null=True, verbose_name='Affects Indigenous - Details'),
),
]

View File

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-31 14:42
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0015_auto_20171030_1550'),
]
operations = [
migrations.AddField(
model_name='casestudy',
name='definition_of_affected_territories',
field=models.CharField(blank=True, default=None, help_text='In your own words, define the territories that the project will affect.', max_length=512, null=True, verbose_name='Definition of affected territories'),
),
migrations.AddField(
model_name='casestudy',
name='official_project_documents',
field=models.FileField(blank=True, default=None, help_text='Attach any legal or official documents that relate to the project.', null=True, upload_to='', verbose_name='Official project documents'),
),
migrations.AddField(
model_name='casestudy',
name='other_documents',
field=models.FileField(blank=True, default=None, help_text='Attach any other documents that relate to the project.', null=True, upload_to='', verbose_name='Other documents'),
),
migrations.AddField(
model_name='casestudy',
name='shown_on_other_platforms',
field=models.NullBooleanField(default=None, help_text='Tick the box if you would like us to show this case study on other social media platforms', verbose_name='Show on other platforms?'),
),
migrations.AddField(
model_name='casestudy',
name='shown_on_other_platforms_detail',
field=models.CharField(blank=True, help_text='List the social media platforms that you would like us to specifically publish the case study on', max_length=128, null=True, verbose_name='Show on other platforms - Detail'),
),
]

View File

@ -1,9 +1,12 @@
import datetime
from urllib import parse
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django_extensions.db.fields import AutoSlugField from django_extensions.db.fields import AutoSlugField
from django_countries.fields import CountryField from django_countries.fields import CountryField
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from . import validators
class CaseStudy(models.Model): class CaseStudy(models.Model):
@ -58,6 +61,38 @@ class CaseStudy(models.Model):
('PROJCD', _('Projected Project')), ('PROJCD', _('Projected Project')),
) )
GENERATION_TECHNOLOGY_CHOICES = (
(_('Wind energy'), (
('SSWE', _('Small-scale (less than 500kW)')),
('LSWE', _('Large-scale (more than 500kW)'))
)),
(_('Photovoltaic electricity'), (
('SSPV', _('Small-scale (less than 500kW)')),
('LSPV', _('Large-scale (more than 500kW)'))
)),
(_('Hydroelectric'), (
('SHYD', _('Small-scale (less than 1MW)')),
('MHYD', _('Medium-scale (between 1-20MW)')),
('LHYD', _('Large-scale (more than 20MW - often not considered renewable)')),
)),
('STHE', _('Solar thermal electricity (e.g using parabolic reflectors)')),
('GEOT', _('Geothermal electricity')),
('BIOG', _('Biogas turbine')),
('OTHB', _('Other biomass (including liquid/solid biofuel)')),
('OTHR', _('Other (tidal, wave etc)'))
)
POWER_TECHNOLOGY_CHOICES = (
('PT', _('Power transmission (grid lines, substations etc)')),
('ES', _('Energy storage (pumped storage, compressed air, battery systems etc')),
('OT', _('Others'))
)
# 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),
(datetime.datetime.now().year + 41))]
## ##
# Meta Fields # Meta Fields
## ##
@ -72,11 +107,16 @@ class CaseStudy(models.Model):
) )
# Date and time of submission # Date and time of submission
date_created = models.DateTimeField(auto_now=True, null=False) date_created = models.DateTimeField(auto_now_add=True, null=False)
# Slug derived from entry_name, used in urls for SEO # 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'])
##
# First Screen
##
# 1.1 # 1.1
entry_name = models.CharField( entry_name = models.CharField(
verbose_name=_("Entry Name"), verbose_name=_("Entry Name"),
@ -86,7 +126,11 @@ class CaseStudy(models.Model):
) )
# N/A - Not explicitly listed in spec # N/A - Not explicitly listed in spec
location = models.PointField() location = models.PointField(
verbose_name=_("Project location"),
help_text=_("Place a marker using the tools on the left of the map. Zoom in as far as you can so the placement \
is accurate (important)")
)
# 1.2 # 1.2
sector_of_economy = models.CharField( sector_of_economy = models.CharField(
@ -106,7 +150,10 @@ class CaseStudy(models.Model):
) )
# 1.4 # 1.4
country = CountryField() country = CountryField(
verbose_name=_("Country field"),
help_text=_("Select the country of the project")
)
# 1.5.1 # 1.5.1
area_of_land = models.IntegerField( area_of_land = models.IntegerField(
@ -125,9 +172,10 @@ class CaseStudy(models.Model):
# 1.5.3 # 1.5.3
land_ownership_details = models.CharField( land_ownership_details = models.CharField(
verbose_name=_("Land ownership details"), verbose_name=_("Land ownership details"),
help_text=_("Add any details and other remarks about the land\ help_text=_("Please specify details about land ownership if you chose 'other'"),
ownership"), max_length=256,
max_length=256 null=True,
blank=True,
) )
# 1.5.4 # 1.5.4
@ -157,7 +205,7 @@ class CaseStudy(models.Model):
# 1.5.6 # 1.5.6
affects_indigenous = models.BooleanField( affects_indigenous = models.BooleanField(
verbose_name=_("Affects indigenous people?"), verbose_name=_("Affects indigenous people?"),
help_text=_("Does the project affect indigenous people?") help_text=_("Does the project affect indigenous communities?")
) )
# 1.5.6.1 # 1.5.6.1
@ -165,7 +213,10 @@ class CaseStudy(models.Model):
verbose_name=_("Affects Indigenous - Details"), verbose_name=_("Affects Indigenous - Details"),
help_text=_("What group of indigenous people does the community belong\ help_text=_("What group of indigenous people does the community belong\
to?"), to?"),
max_length=256 max_length=256,
default=None,
null=True,
blank=True
) )
# 1.6 # 1.6
@ -176,6 +227,28 @@ class CaseStudy(models.Model):
choices=PROJECT_STATUS_CHOICES choices=PROJECT_STATUS_CHOICES
) )
# 1.7
start_year = models.IntegerField(
verbose_name=_("Start year"),
help_text=_("Select the year the project was started. \
If the project hasn't begun, select the projected start year."),
choices=YEAR_CHOICES,
default=None,
null=True,
blank=True
)
# 1.8
completion_year = models.IntegerField(
verbose_name=_("Completion year"),
help_text=_("Select the year the project was completed. \
If the project hasn't finished, select the projected completion year."),
choices=YEAR_CHOICES,
default=None,
null=True,
blank=True
)
# 1.9 # 1.9
synopsis = models.TextField( synopsis = models.TextField(
verbose_name=_("Synopsis"), verbose_name=_("Synopsis"),
@ -193,24 +266,287 @@ class CaseStudy(models.Model):
here.") here.")
) )
# 1.15 # 1.11
project_owners = models.CharField(
verbose_name=_("Project and facility owners"),
help_text=_("List companies or organisations that own the project and/or facilities. Separate with a comma."),
max_length=120,
default=None,
null=True,
blank=True
)
# 1.12
shareholders = models.CharField(
verbose_name=_("Shareholders of the project owners"),
help_text=_("List shareholders of the project owners you've just listed. Separate with a comma."),
max_length=120,
default=None,
null=True,
blank=True
)
# 1.13
financial_institutions = models.CharField(
verbose_name=_("Financial institutions"),
help_text=_("List banks and other financial institutions that have or are considering extending loans \
or guarantees to the project. Separate with a comma."),
max_length=120,
default=None,
null=True,
blank=True
)
# 1.14
energy_customers = models.CharField(
verbose_name=_("Energy consumers"),
help_text=_("List any wholesale energy customers that take energy from the development. E.g. 'national \
grids' or private energy suppliers."),
max_length=120,
default=None,
null=True,
blank=True
)
# 1.15.1
image = models.ImageField( image = models.ImageField(
verbose_name=_("Image") verbose_name=_("Image")
) )
# 1.16 # 1.15.2
video = models.URLField( image_caption = models.CharField(
verbose_name=_("Video"), verbose_name=_("Image caption"),
max_length=43 max_length=500,
default=None,
null=True,
) )
# 1.18 # 1.15.3
image_credit = models.CharField(
verbose_name=_("Image credit(s)"),
max_length=200,
default=None,
null=True,
)
# 1.16.1
video = models.URLField(
verbose_name=_("YouTube Video"),
help_text=_("Copy the URL to a related YouTube™ video that relates to the case study."),
max_length=43,
validators=[validators.YoutubeURLValidator()]
)
# 1.16.2
video_caption = models.CharField(
verbose_name=_("Video caption"),
max_length=500,
default=None,
null=True,
)
# 1.16.3
video_credit = models.CharField(
verbose_name=_("Video credit(s)"),
max_length=500,
default=None,
null=True,
)
# 1.17.1
media_coverage_mainstream = models.TextField(
verbose_name=_("Links to media reports"),
help_text=_("Provide any links to mainstream media coverage."),
max_length=500,
default=None,
null=True,
)
# 1.17.2
media_coverage_independent = models.TextField(
verbose_name=_("Independent grassroots reports"),
help_text=_("Provide any links to grassroots/independent media coverage."),
max_length=500,
default=None,
null=True,
)
# 1.18.1
community_voices = models.TextField( community_voices = models.TextField(
verbose_name=_("Community Voices"), verbose_name=_("Community Voices"),
help_text=_("Add any direct quotes from members of the community that\ help_text=_("Add any direct quotes from members of the community that \
relate to this project") relate to this project")
) )
# 1.18.2
direct_comms = models.TextField(
verbose_name=_("Reports of direct communications"),
help_text=_("Add any reports of direct communication between community members and \
representatives of developers/companies/investors."),
max_length=500,
default=None,
null=True,
)
# 1.18.3
social_media_links = models.TextField(
verbose_name=_("Social media links"),
help_text=_("Add any links to social media accounts directly relating to the project."),
max_length=500,
default=None,
null=True,
blank=True
)
##
# Second Screen
##
# 2.1.1
generation_technology = models.CharField(
verbose_name=_("Generation technology"),
help_text=_("Select the type of renewable energy generation that most applies to this case study."),
max_length=4,
choices=GENERATION_TECHNOLOGY_CHOICES,
default=None,
null=True,
blank=True
)
# 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"),
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,
default=None,
null=True,
blank=True
)
# 2.1.1.14
generation_technology_other = models.CharField(
verbose_name=_("Other generation type"),
help_text=_("If you selected other, please specify the generation technology (e.g. tidal, wave etc)"),
max_length=200,
default=None,
null=True,
blank=True
)
# 2.1.2
total_generation_capacity = models.PositiveIntegerField(
verbose_name=_("Total generation capacity (in kW)"),
help_text=_("Please enter the total generation capacity of the project in kW"),
default=None,
null=True,
blank=True,
)
# 2.1.3 - autocomplete_light queryset
# 2.1.4
total_investment = models.IntegerField(
verbose_name=_("Total investment (in USD)"),
help_text=_("The approximate total investment for the project in USD."),
default=None,
null=True,
blank=True
)
# 2.1.5
technical_or_economic_details = models.CharField(
verbose_name=_("Additional technical or economic details"),
help_text=_("Specify any additional technical or economic details relating to the project."),
max_length=500,
default=None,
null=True,
blank=True
)
# 2.2 - Only if 1.2.2 selected
# 2.2.1
power_technology = models.CharField(
verbose_name=_("Power technology"),
help_text=_("Select the related energy technology."),
max_length=2,
choices=POWER_TECHNOLOGY_CHOICES,
default=None,
null=True,
blank=True
)
power_technology_other = models.CharField(
verbose_name=_("Other power technology"),
help_text=_("If you answered 'others', please specify the power technologies."),
max_length=128,
default=None,
null=True,
blank=True
)
energy_storage_capacity = models.IntegerField(
verbose_name=_("Energy storage capacity"),
help_text=_("Enter the total capacity of the energy storage system."),
default=None,
null=True,
blank=True
)
##
# Third Screen
##
##
# Fourth Screen
##
# 4.1
official_project_documents = models.FileField(
verbose_name=_("Official project documents"),
help_text=_("Attach any legal or official documents that relate to the project."),
default=None,
null=True,
blank=True
)
# 4.2
other_documents = models.FileField(
verbose_name=_("Other documents"),
help_text=_("Attach any other documents that relate to the project."),
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."),
max_length=512,
default=None,
null=True,
blank=True
)
# 4.4
shown_on_other_platforms = models.NullBooleanField(
verbose_name=_("Show on other platforms?"),
help_text=_("Tick the box if you would like us to show this case study on other social media platforms"),
default=None,
null=True,
blank=True
)
# 4.4.1
shown_on_other_platforms_detail = models.CharField(
verbose_name=_("Show on other platforms - Detail"),
help_text=_("List the social media platforms that you would like us to specifically publish the case study on"),
max_length=128,
null=True,
blank=True
)
def __str__(self): def __str__(self):
"""The String representation of the case study. (Entry name with country name.)""" """The String representation of the case study. (Entry name with country name.)"""
return "%s in %s" % (self.entry_name, self.country.name) return "%s in %s" % (self.entry_name, self.country.name)
@ -227,3 +563,7 @@ class CaseStudy(models.Model):
self.slug = slugify(self.entry_name) self.slug = slugify(self.entry_name)
# Continue normal save method by calling original save method. # Continue normal save method by calling original save method.
super(CaseStudy, self).save(*args, **kwargs) super(CaseStudy, self).save(*args, **kwargs)
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]

View File

@ -1,4 +1,10 @@
from moderation import moderation from moderation import moderation
from moderation.moderator import GenericModerator
from apps.map.models import CaseStudy from apps.map.models import CaseStudy
moderation.register(CaseStudy) # Uses default moderation settings
class CaseStudyModerator(GenericModerator):
notify_user = True
auto_approve_for_superusers = True
moderation.register(CaseStudy, CaseStudyModerator)

View File

@ -17,7 +17,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row" style="background-color: #e3f3fd;"> <div class="row" style="background-color: #e3f3fd;">
<div class="col-lg-8 border-top-0"> <div class="col-lg-8 border-top-0">
<a class="btn btn-info" style="margin:15px 0;padding-left:20px;left:-10px;position:absolute;" href="{% url 'index' %}" role="button"><- {% trans "Back to Map" %}</a> <a class="btn btn-info" style="margin:15px 0;padding-left:20px;left:-10px;position:absolute;" href="{% url 'index' %}" role="button"><i class="fa fa-arrow-left" aria-hidden="true"></i> {% trans "Back to Map" %}</a>
<div style="margin-top:70px;padding:0 20px;"> <div style="margin-top:70px;padding:0 20px;">
<h1>{{case_study.entry_name}}</h1> <h1>{{case_study.entry_name}}</h1>
<p>{{case_study.synopsis}}</p> <p>{{case_study.synopsis}}</p>
@ -33,13 +33,13 @@
<span class="badge badge-pill bg-info">{{case_study.country.name}}</span> <span class="badge badge-pill bg-info">{{case_study.country.name}}</span>
</br> </br>
<small class="text-muted">Created {{case_study.date_created|naturaltime}} by <i>{{case_study.author.}}</i></small> <small class="text-muted">Created {{case_study.date_created|naturaltime}} by <i>{{case_study.author.}}</i></small>
</div> </div>
<a class="btn btn-primary btn-lg float-right" href="#" role="button">Get Involved</a> <a class="btn btn-primary btn-lg float-right" href="#" role="button">Get Involved</a>
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<div class="embed-responsive embed-responsive-16by9"> <div class="embed-responsive embed-responsive-16by9">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ScMzIvxBSi4?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/{{case_study.get_video_id}}?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>
</div> </div>
</div> </div>
</div> </div>

View File

@ -31,4 +31,95 @@
// See GeometryField source (static/leaflet/leaflet.forms.js) to override more stuff... // See GeometryField source (static/leaflet/leaflet.forms.js) to override more stuff...
}); });
</script> </script>
<!-- Conditional logic for hiding and un-hiding fields. -->
<script type="text/javascript">
// Here we define the fields we need to conditionally toggle.
// TODO: Move this knowledge out of the template
var conditionalFields = [{
"field": "#id_land_ownership",
"showHide": ["#div_id_land_ownership_details"],
"condition": "OTH"
},
{
"field": "#id_power_technology",
"showHide": ["#div_id_power_technology_other"],
"condition": "OT"
},
{
"field": "#id_sector_of_economy",
"showHide": ["#div_id_generation_technology",
"#div_id_biomass_detail",
"#div_id_generation_technology_other",
"#div_id_total_generation_capacity",
"#div_id_total_investment",
"#div_id_technical_or_economic_details"],
"condition": ["WND","SOL","HYD"]
}];
// Here we define the checkboxes that we need to use to
// conditionally toggle fields - they use slightly different
// logic as they rely on the 'checked' attribute rather than value.
var conditionalCheckboxes = [{
"checkbox": "#id_affects_indigenous",
"showHide": "#div_id_affects_indigenous_detail"
}];
// Define a function that hides the field and then creates a listener to toggle the field.
// Takes a single conditionalField dictionary with (field, showHide and condition).
function addConditionalField(item) {
hideAll(item.showHide);
$(item.field).change(function(){
// Get the value of the option
var value = $(this).val();
// Check the value matches any of the conditions.
if (isInArray(value, item.condition)){
showAll(item.showHide);
} else {
hideAll(item.showHide);
}
});
}
// This function does the same as addConditionalField except it checks the status of
// checkboxes instead of fields.
function addConditionalCheckbox(item) {
$(item.showHide).hide();
$(item.checkbox).change(function(){
if ($(this).is(":checked")) {
$(item.showHide).show();
} else {
$(item.showHide).hide();
}
});
}
// Helper functions
function show(tag) {
$(tag).show();
}
function hide(tag) {
$(tag).hide();
}
function showAll(tags) {
tags.forEach(show);
}
function hideAll(tags) {
tags.forEach(hide);
}
function isInArray(value, array) {
return array.indexOf(value) > -1;
}
conditionalFields.forEach(addConditionalField);
conditionalCheckboxes.forEach(addConditionalCheckbox);
</script>
{% endblock %} {% endblock %}

View File

@ -100,13 +100,13 @@
}).addTo(map); }).addTo(map);
}); });
// Add an on-click listener for map click events. Show popup with button to submit a casestudy <!--// Add an on-click listener for map click events. Show popup with button to submit a casestudy-->
map.on('click', function(e) { <!--map.on('click', function(e) {-->
var popup = L.popup() <!--var popup = L.popup()-->
.setLatLng(e.latlng) <!--.setLatLng(e.latlng)-->
.setContent("<a class='btn btn-primary btn-sm' href='{% url 'create' %}?lat="+e.latlng.lat+"&lng="+e.latlng.lng+"' role='button'>{% trans "Submit a Case Study" %}</a>") <!--.setContent("<a class='btn btn-primary btn-sm' href='{% url 'create' %}?lat="+e.latlng.lat+"&lng="+e.latlng.lng+"' role='button'>{% trans "Submit a Case Study" %}</a>")-->
.openOn(map); <!--.openOn(map);-->
}); <!--});-->
} }
</script> </script>
{% endblock %} {% endblock %}

5
apps/map/validators.py Normal file
View File

@ -0,0 +1,5 @@
from django.core.validators import RegexValidator
class YoutubeURLValidator(RegexValidator):
regex = r'https?:\/\/(((www.)?youtube.com\/((watch\?v=)|(watch\/)))|(youtu.be\/))([A-z0-9]{1,11}).+'

7
apps/profiles/forms.py Normal file
View File

@ -0,0 +1,7 @@
from django.forms import ModelForm
from django.contrib.auth import get_user_model
class UpdateProfile(ModelForm):
class Meta:
model = get_user_model()

View File

@ -1,2 +1,6 @@
{% extends "base_page.html" %} {% extends "base_page.html" %}
Profile page Profile page
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update" />
</form>

View File

@ -3,5 +3,19 @@ from django.conf.urls import url
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.Profile.as_view(), name='profile'), url(
regex=r'^~redirect/$',
view=views.UserRedirectView.as_view(),
name='redirect'
),
url(
regex=r'^$',
view=views.UserDetailView.as_view(),
name='detail'
),
url(
regex=r'^~update/$',
view=views.UserUpdateView.as_view(),
name='update'
),
] ]

View File

@ -1,5 +1,46 @@
from django.views.generic.base import TemplateView from django.core.urlresolvers import reverse
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth import get_user_model
class Profile(TemplateView): class UserDetailView(LoginRequiredMixin, DetailView):
template_name = "profiles/profile.html" model = get_user_model()
# These next two lines tell the view to index lookups by username
slug_field = 'username'
slug_url_kwarg = 'username'
def get_object(self):
return get_user_model().objects.get(username=self.request.user.username)
class UserRedirectView(LoginRequiredMixin, RedirectView):
permanent = False
def get_redirect_url(self):
return reverse('profile:detail')
class UserUpdateView(LoginRequiredMixin, UpdateView):
fields = ['first_name', 'last_name']
# we already imported User in the view code above, remember?
model = get_user_model()
# send the user back to their own page after a successful update
def get_success_url(self):
return reverse('profile:detail')
def get_object(self):
# Only get the User record for the user making the request
return get_user_model().objects.get(username=self.request.user.username)
class UserListView(LoginRequiredMixin, ListView):
model = get_user_model()
# These next two lines tell the view to index lookups by username
slug_field = 'username'
slug_url_kwarg = 'username'

View File

@ -16,6 +16,7 @@ services:
volumes: volumes:
- ./apps:/app/apps - ./apps:/app/apps
- ./ojusomap:/app/ojusomap - ./ojusomap:/app/ojusomap
- ./support:/app/support
- /containers/map/static:/app/static - /containers/map/static:/app/static
- /containers/map/gunicorn.sock:/app/gunicorn.sock - /containers/map/gunicorn.sock:/app/gunicorn.sock
env_file: env_file:

View File

@ -1,4 +1,4 @@
version: "3" version: '3'
services: services:
map: map:
build: . build: .

View File

@ -30,7 +30,10 @@ SECRET_KEY = os.getenv(
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = bool(int(os.getenv('DEBUG', False))) DEBUG = bool(int(os.getenv('DEBUG', False)))
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split() if DEBUG:
ALLOWED_HOSTS = ['*']
else:
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split()
# Application definition # Application definition
@ -51,6 +54,7 @@ INSTALLED_APPS = [
'whitenoise.runserver_nostatic', 'whitenoise.runserver_nostatic',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.gis', 'django.contrib.gis',
'avatar',
'bootstrap3', 'bootstrap3',
'cas_server', 'cas_server',
'compressor', 'compressor',
@ -62,6 +66,7 @@ INSTALLED_APPS = [
'raven.contrib.django.raven_compat', 'raven.contrib.django.raven_compat',
'rest_framework', 'rest_framework',
'rest_framework_gis', 'rest_framework_gis',
'storages'
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -174,6 +179,16 @@ LOCALE_PATHS = [
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/ # https://docs.djangoproject.com/en/1.11/howto/static-files/
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_S3_ENDPOINT_URL = "https://ojuso-media.nyc3.digitaloceanspaces.com"
AWS_STORAGE_BUCKET_NAME = "ojuso-media"
AWS_LOCATION = ""
AWS_S3_REGION_NAME = "nyc3"
AWS_S3_CUSTOM_DOMAIN = "ojuso-media.nyc3.digitaloceanspaces.com/ojuso-media"
AWS_ACCESS_KEY_ID = "RUZTFVKPCNJIWCVUVJFW"
AWS_SECRET_ACCESS_KEY = "pTZAnmtvGzFBdI/jwtwRoFW5eK7eJ8FLFxr1/Jb+Yq4"
STATIC_ROOT = os.path.join(BASE_DIR, 'static/') STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
STATIC_URL = os.getenv("STATIC_URL", '/static/') STATIC_URL = os.getenv("STATIC_URL", '/static/')
STATICFILES_FINDERS = [ STATICFILES_FINDERS = [
@ -184,7 +199,7 @@ STATICFILES_FINDERS = [
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = os.getenv("MEDIA_URL", '/media/') MEDIA_URL = os.getenv("MEDIA_URL", "https://ojuso-media.nyc3.digitaloceanspaces.com/ojuso-media/")
# Cache # Cache
# https://docs.djangoproject.com/en/1.11/topics/cache/ # https://docs.djangoproject.com/en/1.11/topics/cache/
@ -248,3 +263,13 @@ RAVEN_CONFIG = {
# release based on the git info. # release based on the git info.
'release': raven.fetch_git_sha(os.path.dirname(os.pardir)), 'release': raven.fetch_git_sha(os.path.dirname(os.pardir)),
} }
# Avatars
AVATAR_GRAVATAR_DEFAULT = "mm"
AVATAR_CLEANUP_DELETED = True
# Messages
from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.ERROR: 'danger'
}

View File

@ -0,0 +1,36 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block title %}User: {{ object.username }}{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-12">
<h2>{{ object.username }}</h2>
{% if object.name %}
<p>{{ object.name }}</p>
{% endif %}
</div>
</div>
{% if object == request.user %}
<!-- Action buttons -->
<div class="row">
<div class="col-sm-12">
<a class="btn btn-primary" href="{% url 'profile:update' %}" role="button">{% trans 'Change Name' %}</a>
<a class="btn btn-primary" href="" role="button">E-Mail</a>
<!-- Your Stuff: Custom user template urls -->
</div>
</div>
<!-- End Action buttons -->
{% endif %}
</div>
{% endblock content %}

View File

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block title %}{{ user.username }}{% endblock %}
{% block content %}
<h1>{{ user.username }}</h1>
<form class="form-horizontal" method="post" action="{% url 'profile:update' %}">
{% csrf_token %}
{{ form|crispy }}
<div class="control-group">
<div class="controls">
<button type="submit" class="btn">Update</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% load static i18n %}
{% block title %}Members{% endblock %}
{% block content %}
<div class="container">
<h2>Users</h2>
<div class="list-group">
{% for user in user_list %}
<a href="" class="list-group-item">
<h4 class="list-group-item-heading">{{ user.username }}</h4>
</a>
{% endfor %}
</div>
</div>
{% endblock content %}

View File

@ -1,4 +1,5 @@
{% spaceless %} {% spaceless %}
{% load avatar_tags %}
{% load flatpages %} {% load flatpages %}
{% load i18n %} {% load i18n %}
{% load leaflet_tags %} {% load leaflet_tags %}
@ -10,7 +11,9 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>{% block page_title %}Ojuso{% endblock %}</title> <title>{% block page_title %}Ojuso{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="{% static 'map/bundle.js'%}"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous"></script>
<!--{# <script src="{% static 'map/bundle.js'%}"></script> #}-->
{# Additional Stylesheets #} {# Additional Stylesheets #}
{% block stylesheets %} {% block stylesheets %}
@ -22,42 +25,68 @@
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{% url 'index' %}"> <a class="navbar-brand" href="{% url 'index' %}">
<img src="{% static 'map/images/ojuso-logo-black.png' %}" height="40px"/> <img src="{% static 'map/images/ojuso-logo-black.png' %}" height="20px"/>
</a> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<li class="nav-item"> <ul class="navbar-nav mr-auto">
<a class="nav-link" href="#">Map <span class="sr-only">(current)</span></a> <li class="nav-item">
<a class="nav-link" href="{% url 'index' %}">{% trans 'Map' %}<span class="sr-only">(current)</span></a>
</li>
{% get_flatpages as flatpages %}
{% for page in flatpages %}
<li class="nav-item"><a class="nav-link" href="{{page.url}}">{{page.title}}</a></li>
{% endfor %}
</ul>
<ul class="navbar-nav my-2 my-lg-0">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="btn btn-outline-info" href="{% url 'create' %}"><i class="fa fa-plus" aria-hidden="true"> New Case Study</i></a>
</li>
<li class="nav-item dropdown">
<a style="margin:-10px 0 -10px 0" class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img src="{% avatar_url user %}" class="rounded-circle" width="40" height="40" style="position:relative;margin-right:5px"/><span>{{user}}</span>
</a>
<div class="dropdown-menu dropdown-menu-right" style="padding-bottom:0px" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{% url 'avatar_change' %}"><i class="fa fa-cog" aria-hidden="true"></i> Change Avatar</a>
<a class="dropdown-item" href="{% url 'profile:detail' %}"><i class="fa fa-cog" aria-hidden="true"></i> Profile</a>
<div class="dropdown-divider" style="margin-bottom:0px"></div>
<a class="dropdown-item bg-danger" style="color:white;padding:0.5rem 1.5rem" href="{% url 'auth_logout' %}"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> {% trans 'Logout' %}</a>
</div>
</li> </li>
{% get_flatpages as flatpages %}
{% for page in flatpages %} {% else %}
<li class="nav-item"><a class="nav-link" href="{{page.url}}">{{page.title}}</a></li> <li class="nav-item"><a style="margin: 5px;" class="btn btn-outline-primary" href={% url 'auth_login' %}>{% trans 'Login' %}</a></li>
{% endfor %} <li class="nav-item"><a style="margin: 5px;" class="btn btn-info" href={% url 'registration_register' %}>{% trans 'Register' %}</a></li>
</ul> {% endif %}
</ul>
</div> </div>
{% if user.is_authenticated %} </nav>
<span>{{user}}</span>
<a class="btn btn-primary" href={% url 'auth_logout' %}>Logout</a> {% if messages %}
{% else %} {% for message in messages %}
<a style="margin: 5px;" class="btn btn-primary" href={% url 'auth_login' %}>Login</a> <div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
<a style="margin: 5px;" class="btn btn-info" href={% url 'registration_register' %}>Register</a> {{ message }}
{% endif %} <button type="button" class="close" data-dismiss="alert" aria-label="Close">
</nav> <span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endif %}
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</body> </body>
{# CDN Javascript #} {# CDN Javascript #}
<script src="//code.jquery.com/jquery-3.2.1.min.js" <script src="//code.jquery.com/jquery-3.2.1.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
crossorigin="anonymous"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
</script>
{% block scripts %}{% endblock %} {% block scripts %}{% endblock %}
</html> </html>
{% endspaceless %} {% endspaceless %}

View File

@ -1,10 +1,9 @@
{% extends 'base_email.html' %} {% extends 'base_email.html' %}
{% block content %} {% block content %}
<div align="left"> <div align="left">
{{user}},<br><br> {{user}},<br><br>
To activate your account and log in, <a href="https://animalrightsmap.org{% url 'registration_activate' activation_key %}">click here</a>.<br> To activate your account and log in, <a href="https://animalrightsmap.org{% url 'registration_activate' activation_key %}">click here</a>.<br>
This link will expire in 7 days so be sure do it soon.<br><br> This link will expire in 7 days so be sure do it soon.<br><br>
See you on the activist trail!<br><br> - Ojuso
- Animal Rights Map
</div> </div>
{% endblock %} {% endblock %}

View File

@ -9,8 +9,8 @@
{% block content %} {% block content %}
<div class="container" style="max-width:520px;"> <div class="container" style="max-width:520px;">
<div class="page-lead"> <div class="page-lead">
<h2>Login</h2> <h2>{% trans 'Login' %}</h2>
<p class="lead">{% trans "Welcome!" %}</p> <p class="lead">{% trans 'Welcome!' %}</p>
</div> </div>
{% bootstrap_messages %} {% bootstrap_messages %}
<form action="{% url 'auth_login' %}?next={{next}}" method="post"> <form action="{% url 'auth_login' %}?next={{next}}" method="post">

View File

@ -2,21 +2,22 @@
{% load bootstrap3 %} {% load bootstrap3 %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load envelope_tags %} {% load envelope_tags %}
{% load i18n %}
{% block page_name %}Registration{% endblock %} {% block page_name %}Registration{% endblock %}
{% block content %} {% block content %}
<div class="container" style="max-width:520px;"> <div class="container" style="max-width:520px;">
<div class="page-lead"> <div class="page-lead">
<h2>Registration</h2> <h2>{% trans 'Registration' %}</h2>
<p class="lead">Create your account and get active!</p> <p class="lead">{% trans 'Create your account and get active!' %}</p>
</div> </div>
{% bootstrap_messages %} {% bootstrap_messages %}
<form action="{% url 'registration_register' %}" method="post"> <form action="{% url 'registration_register' %}" method="post">
{% csrf_token %} {% csrf_token %}
{% antispam_fields %} {% antispam_fields %}
{{ form|crispy }} {{ form|crispy }}
<input class="btn btn-success pull-right" type="submit" name"submit" value"Register"/> <input class="btn btn-success pull-right" type="submit" name="su/bmit" value="{% trans 'Register'%}"/>
</form> </form>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -51,12 +51,13 @@ apirouter.register(r'case-studies', CaseStudyViewSet)
urlpatterns = [ urlpatterns = [
url(r'api/', include(apirouter.urls)), url(r'api/', include(apirouter.urls)),
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
url(r'^avatar/', include('avatar.urls')),
url(r'^cas/', include('cas_server.urls', namespace='cas_server')), url(r'^cas/', include('cas_server.urls', namespace='cas_server')),
# url(r'^contact/', include('apps.contact.urls'), name="contact") # url(r'^contact/', include('apps.contact.urls'), name="contact"),
] ]
urlpatterns += i18n_patterns( urlpatterns += i18n_patterns(
url(r'^accounts/profile/', include('apps.profiles.urls')), url(r'^accounts/profile/', include('apps.profiles.urls', namespace="profile")),
# url(r'^accounts/logout/?$', include('django.contrib.auth.views.logout'), {'next_page': '/'}), # url(r'^accounts/logout/?$', include('django.contrib.auth.views.logout'), {'next_page': '/'}),
url(r'^accounts/', include('registration.backends.default.urls')), url(r'^accounts/', include('registration.backends.default.urls')),
url(r'', include('apps.map.urls'), name="map"), url(r'', include('apps.map.urls'), name="map"),

View File

@ -1,7 +1,10 @@
appdirs==1.4.3 appdirs==1.4.3
brotlipy==0.7.0 brotlipy==0.7.0
boto==2.48.0
boto3==1.4.7
Django==1.11.6 Django==1.11.6
django-appconf==1.0.2 django-appconf==1.0.2
django-avatar==4.0.1
django-bootstrap3==8.2.3 django-bootstrap3==8.2.3
django-braces==1.11.0 django-braces==1.11.0
django-cas-server==0.8.0 django-cas-server==0.8.0
@ -15,6 +18,7 @@ django-geojson==2.10.0
-e git://github.com/makinacorpus/django-leaflet.git@a43acc5fed6674b413a6fab0feeb7c44e67c2ca8#egg=django-leaflet -e git://github.com/makinacorpus/django-leaflet.git@a43acc5fed6674b413a6fab0feeb7c44e67c2ca8#egg=django-leaflet
django-moderation==0.5.0 django-moderation==0.5.0
django-registration-redux==1.6 django-registration-redux==1.6
django-storages==1.6.5
djangorestframework==3.6.3 djangorestframework==3.6.3
djangorestframework-gis==0.11.2 djangorestframework-gis==0.11.2
gunicorn==19.7.1 gunicorn==19.7.1