Add registration and login templates plus UI stuff, moderation
This commit is contained in:
parent
f8dc44b4a6
commit
049ca29e77
@ -47,6 +47,8 @@ RUN wget https://nodejs.org/dist/v7.10.0/node-v7.10.0-linux-x64.tar.gz\
|
|||||||
&& tar -xvf ../../proj-datumgrid-1.5.tar.gz && cd ../ \
|
&& tar -xvf ../../proj-datumgrid-1.5.tar.gz && cd ../ \
|
||||||
&& ./configure && make && make install
|
&& ./configure && make && make install
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y gettext git
|
||||||
|
|
||||||
# PACKAGES
|
# PACKAGES
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY ./requirements.txt .
|
COPY ./requirements.txt .
|
||||||
@ -59,8 +61,6 @@ COPY ./support/cron/* /etc/cron.d/
|
|||||||
RUN chmod 0644 /etc/cron.d/*\
|
RUN chmod 0644 /etc/cron.d/*\
|
||||||
&& touch /var/log/cron.log
|
&& touch /var/log/cron.log
|
||||||
|
|
||||||
RUN apt-get install -y gettext
|
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
CMD [ "python3", "manage.py", "migrate", "&&", \
|
CMD [ "python3", "manage.py", "migrate", "&&", \
|
||||||
|
0
apps/contact/__init__.py
Normal file
0
apps/contact/__init__.py
Normal file
11
apps/contact/forms.py
Normal file
11
apps/contact/forms.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from envelope.forms import ContactForm
|
||||||
|
from crispy_forms.helper import FormHelper
|
||||||
|
from crispy_forms.layout import Submit
|
||||||
|
|
||||||
|
|
||||||
|
class ContactForm(ContactForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ContactForm, self).__init__(*args, **kwargs)
|
||||||
|
self.helper = FormHelper()
|
||||||
|
self.helper.add_input(Submit('submit', 'Submit',
|
||||||
|
css_class='btn-lg pull-right'))
|
21
apps/contact/templates/envelope/contact.html
Normal file
21
apps/contact/templates/envelope/contact.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load envelope_tags %}
|
||||||
|
|
||||||
|
{% block page_name %}Contact{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-lead">
|
||||||
|
<h2>Contact</h2>
|
||||||
|
<p class="lead">Send us your thoughts and feedback.</p>
|
||||||
|
</div>
|
||||||
|
{% bootstrap_messages %}
|
||||||
|
<form action="{% url 'contact' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% antispam_fields %}
|
||||||
|
{% crispy form %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
3
apps/contact/tests.py
Normal file
3
apps/contact/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
7
apps/contact/urls.py
Normal file
7
apps/contact/urls.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', views.ContactView.as_view(), name='contact'),
|
||||||
|
]
|
12
apps/contact/views.py
Normal file
12
apps/contact/views.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from braces.views import FormMessagesMixin
|
||||||
|
from envelope.views import ContactView
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from .forms import ContactForm
|
||||||
|
|
||||||
|
|
||||||
|
class ContactView(FormMessagesMixin, ContactView):
|
||||||
|
form_invalid_message = _(u"There was an error in the contact form.")
|
||||||
|
form_valid_message = _(u"Thank you for your message.")
|
||||||
|
form_class = ContactForm
|
@ -1,6 +1,12 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from moderation.admin import ModerationAdmin
|
||||||
from leaflet.admin import LeafletGeoAdmin
|
from leaflet.admin import LeafletGeoAdmin
|
||||||
|
|
||||||
from .models import CaseStudy
|
from .models import CaseStudy
|
||||||
|
|
||||||
admin.site.register(CaseStudy, LeafletGeoAdmin)
|
|
||||||
|
class CaseStudyAdmin(ModerationAdmin, LeafletGeoAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(CaseStudy, CaseStudyAdmin)
|
||||||
|
@ -6,15 +6,15 @@ from leaflet.forms.widgets import LeafletWidget
|
|||||||
from .models import CaseStudy
|
from .models import CaseStudy
|
||||||
|
|
||||||
|
|
||||||
class CaseStudyForm(forms.ModelForm):
|
class BaseCaseStudyForm(forms.ModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(CaseStudyForm, self).__init__(*args, **kwargs)
|
super(BaseCaseStudyForm, self).__init__(*args, **kwargs)
|
||||||
self.helper = FormHelper()
|
self.helper = FormHelper()
|
||||||
self.helper.form_id = 'case-study-form'
|
self.helper.form_id = 'case-study-form'
|
||||||
self.helper.form_class = 'form-horizontal'
|
self.helper.form_class = 'form-horizontal'
|
||||||
self.helper.form_method = 'post'
|
self.helper.form_method = 'post'
|
||||||
self.helper.form_action = 'submit'
|
self.helper.form_action = 'add'
|
||||||
self.helper.label_class = 'col-lg-2'
|
self.helper.label_class = 'col-lg-2'
|
||||||
self.helper.field_class = 'col-lg-8'
|
self.helper.field_class = 'col-lg-8'
|
||||||
self.helper.add_input(Submit('submit', 'Submit'))
|
self.helper.add_input(Submit('submit', 'Submit'))
|
||||||
@ -22,4 +22,33 @@ class CaseStudyForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = CaseStudy
|
model = CaseStudy
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
widgets = {'location': LeafletWidget()}
|
widgets = {'location': LeafletWidget(attrs={})}
|
||||||
|
|
||||||
|
|
||||||
|
class ShortCaseStudyForm(BaseCaseStudyForm):
|
||||||
|
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',
|
||||||
|
'affects_indigenous',
|
||||||
|
'affects_indigenous_detail',
|
||||||
|
'project_status',
|
||||||
|
'synopsis',
|
||||||
|
'full_description',
|
||||||
|
'image',
|
||||||
|
'community_voices'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class LongCaseStudyForm(BaseCaseStudyForm):
|
||||||
|
class Meta(BaseCaseStudyForm.Meta):
|
||||||
|
fields = '__all__'
|
||||||
|
169
apps/map/migrations/0004_auto_20171006_1559.py
Normal file
169
apps/map/migrations/0004_auto_20171006_1559.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-06 15:59
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0003_auto_20170521_0643'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='affects_indigenous',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='affects_indigenous_reason',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='associated_companies',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='commodities',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='description',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='financiers',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='generation_type',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='important_lenders',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='like_to_engage_developer',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='like_to_engage_investors',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='link_to_forum',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='project_name',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='proposed_completion',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='proposed_start',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='references',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='supply_chain',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Affects Indigenous - Details',
|
||||||
|
field=models.CharField(default='', help_text='What group of indigenous people does the community belong to?', max_length=256),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Affects indigenous people?',
|
||||||
|
field=models.BooleanField(default=False, help_text='Does the project affect indigenous people?'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Approximate land area',
|
||||||
|
field=models.IntegerField(default=0, help_text='The area of land covered by the project (in km²)'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Community Voices',
|
||||||
|
field=models.TextField(default='', help_text='Add any direct quotes from members of the community that relate to this project'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Describe the ecosystem',
|
||||||
|
field=models.CharField(default='', help_text='In your own words, add more detail about the ecosystem.', max_length=256),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Entry Name',
|
||||||
|
field=models.CharField(default='', help_text='Enter the name of the entry. This should usually be the name of project.', max_length=128),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Full Description',
|
||||||
|
field=models.TextField(default='', help_text='Describe the project in full. Separate paragraphs with a new line Please add as much detail as you feel is necessary here.'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Land ownership',
|
||||||
|
field=models.CharField(choices=[('PRI', 'Private Land'), ('PUB', 'Public Land'), ('COM', 'Community Land'), ('OTH', 'Other')], default='', help_text='What type of ownership does the land fall under?', max_length=3),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Land ownership details',
|
||||||
|
field=models.CharField(default='', help_text='Add any details and other remarks about the land ownership', max_length=256),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Location',
|
||||||
|
field=models.CharField(choices=[('RUR', 'Rural'), ('URB', 'Urban')], default=None, help_text='Select the context that is most applicable to this case study.', max_length=1),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Positive or negative?',
|
||||||
|
field=models.CharField(choices=[('POS', 'Positive'), ('NEG', 'Negative')], default=None, help_text='Is the case study a positive case or a negative case?', max_length=1),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Sector of economy',
|
||||||
|
field=models.CharField(choices=[('Renewable Energy Generation', (('WND', 'Wind'), ('SOL', 'Solar'), ('HYD', 'Hydro'))), ('PG', 'Power Grids'), ('SM', 'Supply of Minerals')], default=None, help_text='Which sector of the renewable energy economy is most relevant?', max_length=2),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Status of Project',
|
||||||
|
field=models.CharField(choices=[('EXSTNG', 'Existing Project'), ('UCONST', 'Under Construction'), ('PROJCD', 'Projected Project')], default=None, help_text='What is the status of the current project?', max_length=6),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Synopsis',
|
||||||
|
field=models.TextField(default=None, 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),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Type of ecosystem',
|
||||||
|
field=models.CharField(choices=[('Water Based', (('MARINE', 'Marine (e.g. Ocean, Sea)'), ('FRESH', 'Freshwater (e.g. Freshwater, Lake)'))), ('Land Based', (('FOREST', 'Forest/Jungle'), ('AGRI', 'Agricultural Land'), ('GRASS', 'Grassland'), ('DESERT', 'Desert (Tundra, Ice or Sand)'), ('WETLND', 'Wetland (Marsh, Mangrove, Peat Soil)'), ('URBAN', 'Urban')))], default=None, help_text='Select the most relevant type of ecosystem.', max_length=6),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
165
apps/map/migrations/0005_auto_20171006_2033.py
Normal file
165
apps/map/migrations/0005_auto_20171006_2033.py
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-06 20:33
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0004_auto_20171006_1559'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Affects Indigenous - Details',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Affects indigenous people?',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Approximate land area',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Community Voices',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Describe the ecosystem',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Entry Name',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Full Description',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Land ownership',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Land ownership details',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Location',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Positive or negative?',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Sector of economy',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Status of Project',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Synopsis',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='Type of ecosystem',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='affects_indigenous',
|
||||||
|
field=models.BooleanField(default=None, help_text='Does the project affect indigenous people?', verbose_name='Affects indigenous people?'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='affects_indigenous_detail',
|
||||||
|
field=models.CharField(default=None, help_text='What group of indigenous people does the community belong to?', max_length=256, verbose_name='Affects Indigenous - Details'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='area_of_land',
|
||||||
|
field=models.IntegerField(default=None, help_text='The area of land covered by the project (in km²)', verbose_name='Approximate land area'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='community_voices',
|
||||||
|
field=models.TextField(default=None, help_text='Add any direct quotes from members of the community that relate to this project', verbose_name='Community Voices'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='describe_ecosystem',
|
||||||
|
field=models.CharField(default=None, help_text='In your own words, add more detail about the ecosystem.', max_length=256, verbose_name='Describe the ecosystem'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='entry_name',
|
||||||
|
field=models.CharField(default=None, help_text='Enter the name of the entry. This should usually be the name of project.', max_length=128, verbose_name='Entry Name'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='full_description',
|
||||||
|
field=models.TextField(default=None, help_text='Describe the project in full. Separate paragraphs with a new line Please add as much detail as you feel is necessary here.', verbose_name='Full Description'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='land_ownership',
|
||||||
|
field=models.CharField(choices=[('PRI', 'Private Land'), ('PUB', 'Public Land'), ('COM', 'Community Land'), ('OTH', 'Other')], default=None, help_text='What type of ownership does the land fall under?', max_length=3, verbose_name='Land ownership'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='land_ownership_details',
|
||||||
|
field=models.CharField(default=None, help_text='Add any details and other remarks about the land ownership', max_length=256, verbose_name='Land ownership details'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='location_context',
|
||||||
|
field=models.CharField(choices=[('RUR', 'Rural'), ('URB', 'Urban')], default=None, help_text='Select the context that is most applicable to this case study.', max_length=1, verbose_name='Location'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='positive_or_negative',
|
||||||
|
field=models.CharField(choices=[('POS', 'Positive'), ('NEG', 'Negative')], default=None, help_text='Is the case study a positive case or a negative case?', max_length=1, verbose_name='Positive or negative?'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='project_status',
|
||||||
|
field=models.CharField(choices=[('EXSTNG', 'Existing Project'), ('UCONST', 'Under Construction'), ('PROJCD', 'Projected Project')], default=None, help_text='What is the status of the current project?', max_length=6, verbose_name='Status of Project'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='sector_of_economy',
|
||||||
|
field=models.CharField(choices=[('Renewable Energy Generation', (('WND', 'Wind'), ('SOL', 'Solar'), ('HYD', 'Hydro'))), ('PG', 'Power Grids'), ('SM', 'Supply of Minerals')], default=None, help_text='Which sector of the renewable energy economy is most relevant?', max_length=2, verbose_name='Sector of economy'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='synopsis',
|
||||||
|
field=models.TextField(default=None, 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, verbose_name='Synopsis'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='type_of_ecosystem',
|
||||||
|
field=models.CharField(choices=[('Water Based', (('MARINE', 'Marine (e.g. Ocean, Sea)'), ('FRESH', 'Freshwater (e.g. Freshwater, Lake)'))), ('Land Based', (('FOREST', 'Forest/Jungle'), ('AGRI', 'Agricultural Land'), ('GRASS', 'Grassland'), ('DESERT', 'Desert (Tundra, Ice or Sand)'), ('WETLND', 'Wetland (Marsh, Mangrove, Peat Soil)'), ('URBAN', 'Urban')))], default=None, help_text='Select the most relevant type of ecosystem.', max_length=6, verbose_name='Type of ecosystem'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
30
apps/map/migrations/0006_auto_20171007_1349.py
Normal file
30
apps/map/migrations/0006_auto_20171007_1349.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-07 13:49
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0005_auto_20171006_2033'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='location_context',
|
||||||
|
field=models.CharField(choices=[('RUR', 'Rural'), ('URB', 'Urban')], help_text='Select the context that is most applicable to this case study.', max_length=3, verbose_name='Location'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='positive_or_negative',
|
||||||
|
field=models.CharField(choices=[('P', 'Positive'), ('N', 'Negative')], help_text='Is the case study a positive case or a negative case?', max_length=1, verbose_name='Positive or negative?'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='sector_of_economy',
|
||||||
|
field=models.CharField(choices=[('Renewable Energy Generation', (('WND', 'Wind'), ('SOL', 'Solar'), ('HYD', 'Hydro'))), ('PG', 'Power Grids'), ('SM', 'Supply of Minerals')], help_text='Which sector of the renewable energy economy is most relevant?', max_length=3, verbose_name='Sector of economy'),
|
||||||
|
),
|
||||||
|
]
|
21
apps/map/migrations/0007_casestudy_slug.py
Normal file
21
apps/map/migrations/0007_casestudy_slug.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-07 14:23
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
import django_extensions.db.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0006_auto_20171007_1349'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='slug',
|
||||||
|
field=django_extensions.db.fields.AutoSlugField(blank=True, editable=False, populate_from=['entry_name']),
|
||||||
|
),
|
||||||
|
]
|
20
apps/map/migrations/0008_casestudy_date_created.py
Normal file
20
apps/map/migrations/0008_casestudy_date_created.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-07 15:02
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0007_casestudy_slug'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='date_created',
|
||||||
|
field=models.DateTimeField(auto_now=True),
|
||||||
|
),
|
||||||
|
]
|
26
apps/map/migrations/0009_auto_20171007_1544.py
Normal file
26
apps/map/migrations/0009_auto_20171007_1544.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-07 15:44
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0008_casestudy_date_created'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='video',
|
||||||
|
field=models.URLField(default="", max_length=43, verbose_name='Video'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='image',
|
||||||
|
field=models.ImageField(upload_to='', verbose_name='Image'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,21 +1,67 @@
|
|||||||
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_countries.fields import CountryField
|
from django_countries.fields import CountryField
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.template.defaultfilters import slugify
|
||||||
|
|
||||||
|
|
||||||
class CaseStudy(models.Model):
|
class CaseStudy(models.Model):
|
||||||
"""Model for case studies submitted to the Ojuso Platform"""
|
"""Model for case studies submitted to the Ojuso Platform"""
|
||||||
|
|
||||||
# Choice lists for dropdowns
|
# Choice lists for drop-downs
|
||||||
SUPPLY_CHAIN_CHOICES = (
|
SECTOR_CHOICES = (
|
||||||
('A', 'Option A'),
|
(_('Renewable Energy Generation'), (
|
||||||
('B', 'Option B'),
|
('WND', _('Wind')),
|
||||||
|
('SOL', _('Solar')),
|
||||||
|
('HYD', _('Hydro')),
|
||||||
|
)),
|
||||||
|
('PG', _('Power Grids')),
|
||||||
|
('SM', _('Supply of Minerals')),
|
||||||
)
|
)
|
||||||
GENERATION_TYPE_CHOICES = (
|
|
||||||
('W', 'Wind'),
|
POSITIVE_NEGATIVE_CHOICES = (
|
||||||
('S', 'Solar'),
|
('P', _('Positive')),
|
||||||
|
('N', _('Negative'))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LAND_OWNERSHIP_CHOICES = (
|
||||||
|
('PRI', _('Private Land')),
|
||||||
|
('PUB', _('Public Land')),
|
||||||
|
('COM', _('Community Land')),
|
||||||
|
('OTH', _('Other')),
|
||||||
|
)
|
||||||
|
|
||||||
|
LOCATION_CONTEXT_CHOICES = (
|
||||||
|
('RUR', _('Rural')),
|
||||||
|
('URB', _('Urban')),
|
||||||
|
)
|
||||||
|
|
||||||
|
TYPE_OF_ECOSYSTEM_CHOICES = (
|
||||||
|
(_('Water Based'), (
|
||||||
|
('MARINE', _('Marine (e.g. Ocean, Sea)')),
|
||||||
|
('FRESH', _('Freshwater (e.g. Freshwater, Lake)')),
|
||||||
|
)),
|
||||||
|
(_('Land Based'), (
|
||||||
|
('FOREST', _('Forest/Jungle')),
|
||||||
|
('AGRI', _('Agricultural Land')),
|
||||||
|
('GRASS', _('Grassland')),
|
||||||
|
('DESERT', _('Desert (Tundra, Ice or Sand)')),
|
||||||
|
('WETLND', _('Wetland (Marsh, Mangrove, Peat Soil)')),
|
||||||
|
('URBAN', _('Urban')),
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
||||||
|
PROJECT_STATUS_CHOICES = (
|
||||||
|
('EXSTNG', _('Existing Project')),
|
||||||
|
('UCONST', _('Under Construction')),
|
||||||
|
('PROJCD', _('Projected Project')),
|
||||||
|
)
|
||||||
|
|
||||||
|
##
|
||||||
|
# Meta Fields
|
||||||
|
##
|
||||||
|
|
||||||
# User who submitted case study
|
# User who submitted case study
|
||||||
author = models.ForeignKey(
|
author = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
@ -25,32 +71,159 @@ class CaseStudy(models.Model):
|
|||||||
editable=False
|
editable=False
|
||||||
)
|
)
|
||||||
|
|
||||||
project_name = models.CharField(max_length=128)
|
# Date and time of submission
|
||||||
# Location of map pin
|
date_created = models.DateTimeField(auto_now=True, null=False)
|
||||||
|
|
||||||
|
# Slug derived from entry_name, used in urls for SEO
|
||||||
|
slug = AutoSlugField(populate_from=['entry_name'])
|
||||||
|
|
||||||
|
# 1.1
|
||||||
|
entry_name = models.CharField(
|
||||||
|
verbose_name=_("Entry Name"),
|
||||||
|
help_text=_("Enter the name of the entry. This should usually be the\
|
||||||
|
name of project."),
|
||||||
|
max_length=128
|
||||||
|
)
|
||||||
|
|
||||||
|
# N/A - Not explicitly listed in spec
|
||||||
location = models.PointField()
|
location = models.PointField()
|
||||||
supply_chain = models.CharField(
|
|
||||||
max_length=1,
|
# 1.2
|
||||||
choices=SUPPLY_CHAIN_CHOICES
|
sector_of_economy = models.CharField(
|
||||||
|
verbose_name=_("Sector of economy"),
|
||||||
|
help_text=_("Which sector of the renewable energy economy is most\
|
||||||
|
relevant?"),
|
||||||
|
max_length=3,
|
||||||
|
choices=SECTOR_CHOICES
|
||||||
)
|
)
|
||||||
generation_type = models.CharField(
|
|
||||||
|
# 1.3
|
||||||
|
positive_or_negative = models.CharField(
|
||||||
|
verbose_name=_("Positive or negative?"),
|
||||||
|
help_text=_("Is the case study a positive case or a negative case?"),
|
||||||
max_length=1,
|
max_length=1,
|
||||||
choices=GENERATION_TYPE_CHOICES
|
choices=POSITIVE_NEGATIVE_CHOICES
|
||||||
)
|
)
|
||||||
associated_companies = models.CharField(max_length=128)
|
|
||||||
financiers = models.CharField(max_length=128)
|
# 1.4
|
||||||
important_lenders = models.CharField(max_length=128)
|
|
||||||
country = CountryField()
|
country = CountryField()
|
||||||
affects_indigenous = models.BooleanField()
|
|
||||||
affects_indigenous_reason = models.TextField()
|
# 1.5.1
|
||||||
proposed_start = models.DateField()
|
area_of_land = models.IntegerField(
|
||||||
proposed_completion = models.DateField()
|
verbose_name=_("Approximate land area"),
|
||||||
description = models.TextField()
|
help_text=_("The area of land covered by the project (in km²)")
|
||||||
link_to_forum = models.URLField()
|
)
|
||||||
image = models.ImageField()
|
|
||||||
references = models.TextField()
|
# 1.5.2
|
||||||
commodities = models.CharField(max_length=128)
|
land_ownership = models.CharField(
|
||||||
like_to_engage_developer = models.BooleanField()
|
verbose_name=_("Land ownership"),
|
||||||
like_to_engage_investors = models.BooleanField()
|
help_text=_("What type of ownership does the land fall under?"),
|
||||||
|
max_length=3,
|
||||||
|
choices=LAND_OWNERSHIP_CHOICES
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.5.3
|
||||||
|
land_ownership_details = models.CharField(
|
||||||
|
verbose_name=_("Land ownership details"),
|
||||||
|
help_text=_("Add any details and other remarks about the land\
|
||||||
|
ownership"),
|
||||||
|
max_length=256
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.5.4
|
||||||
|
location_context = models.CharField(
|
||||||
|
verbose_name=_("Location"),
|
||||||
|
help_text=_("Select the context that is most applicable to this case\
|
||||||
|
study."),
|
||||||
|
max_length=3,
|
||||||
|
choices=LOCATION_CONTEXT_CHOICES
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.5.5
|
||||||
|
type_of_ecosystem = models.CharField(
|
||||||
|
verbose_name=_("Type of ecosystem"),
|
||||||
|
help_text=_("Select the most relevant type of ecosystem."),
|
||||||
|
max_length=6,
|
||||||
|
choices=TYPE_OF_ECOSYSTEM_CHOICES,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.5.5.3
|
||||||
|
describe_ecosystem = models.CharField(
|
||||||
|
verbose_name=_("Describe the ecosystem"),
|
||||||
|
help_text=_("In your own words, add more detail about the ecosystem."),
|
||||||
|
max_length=256,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.5.6
|
||||||
|
affects_indigenous = models.BooleanField(
|
||||||
|
verbose_name=_("Affects indigenous people?"),
|
||||||
|
help_text=_("Does the project affect indigenous people?")
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.5.6.1
|
||||||
|
affects_indigenous_detail = models.CharField(
|
||||||
|
verbose_name=_("Affects Indigenous - Details"),
|
||||||
|
help_text=_("What group of indigenous people does the community belong\
|
||||||
|
to?"),
|
||||||
|
max_length=256
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.6
|
||||||
|
project_status = models.CharField(
|
||||||
|
verbose_name=_("Status of Project"),
|
||||||
|
help_text=_("What is the status of the current project?"),
|
||||||
|
max_length=6,
|
||||||
|
choices=PROJECT_STATUS_CHOICES
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.9
|
||||||
|
synopsis = models.TextField(
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.10
|
||||||
|
full_description = models.TextField(
|
||||||
|
verbose_name=_("Full Description"),
|
||||||
|
help_text=_("Describe the project in full. Separate paragraphs with a\
|
||||||
|
new line Please add as much detail as you feel is necessary\
|
||||||
|
here.")
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.15
|
||||||
|
image = models.ImageField(
|
||||||
|
verbose_name=_("Image")
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.16
|
||||||
|
video = models.URLField(
|
||||||
|
verbose_name=_("Video"),
|
||||||
|
max_length=43
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.18
|
||||||
|
community_voices = models.TextField(
|
||||||
|
verbose_name=_("Community Voices"),
|
||||||
|
help_text=_("Add any direct quotes from members of the community that\
|
||||||
|
relate to this project")
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s in %s" % (self.project_name, self.country.name)
|
"""The String representation of the case study. (Entry name with country name.)"""
|
||||||
|
return "%s in %s" % (self.entry_name, self.country.name)
|
||||||
|
|
||||||
|
def clean(self, *args, **kwargs):
|
||||||
|
"""Perform validation on the model as a whole and throw a ValidationError if anything isn't how it should be."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
"""Override the save method to create a slug when the model is created. Slug is only created and never modified
|
||||||
|
as we are basing our URLs on it and don't want it to change - ever."""
|
||||||
|
if not self.pk:
|
||||||
|
# Newly created object, so set slug
|
||||||
|
self.slug = slugify(self.entry_name)
|
||||||
|
# Continue normal save method by calling original save method.
|
||||||
|
super(CaseStudy, self).save(*args, **kwargs)
|
||||||
|
4
apps/map/moderator.py
Normal file
4
apps/map/moderator.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from moderation import moderation
|
||||||
|
from apps.map.models import CaseStudy
|
||||||
|
|
||||||
|
moderation.register(CaseStudy) # Uses default moderation settings
|
@ -1,11 +0,0 @@
|
|||||||
appdirs==1.4.3
|
|
||||||
Django==1.11.1
|
|
||||||
django-countries==4.5
|
|
||||||
django-crispy-forms==1.6.1
|
|
||||||
django-leaflet==0.22.0
|
|
||||||
gunicorn==19.7.1
|
|
||||||
packaging==16.8
|
|
||||||
psycopg2==2.7.1
|
|
||||||
pyparsing==2.2.0
|
|
||||||
pytz==2017.2
|
|
||||||
six==1.10.0
|
|
17274
apps/map/static/map/bundle.js
Normal file
17274
apps/map/static/map/bundle.js
Normal file
File diff suppressed because one or more lines are too long
BIN
apps/map/static/map/images/ojuso-logo-black.png
Normal file
BIN
apps/map/static/map/images/ojuso-logo-black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
apps/map/static/map/images/ojuso-logo-white.png
Normal file
BIN
apps/map/static/map/images/ojuso-logo-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
@ -1,15 +0,0 @@
|
|||||||
{% load staticfiles %}
|
|
||||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
|
||||||
<div class="container">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<a class="navbar-brand" href="/"><img src="{% static "map/ojuso-logo-white.png" %}" alt="Ojuso Logo"></a>
|
|
||||||
</div>
|
|
||||||
<div id="navbar" class="collapse navbar-collapse">
|
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
{% block nav_links %}
|
|
||||||
{% endblock %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
|||||||
{% extends "map/base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<style>
|
<style>
|
||||||
body {
|
|
||||||
padding-top: 50px;
|
|
||||||
}
|
|
||||||
.page-lead {
|
.page-lead {
|
||||||
padding: 40px 15px;
|
padding: 40px 15px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -15,20 +13,15 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
{% include "map/_nav.html" %}
|
|
||||||
{% block nav_links %}
|
|
||||||
<li><a href="/case-studies">Case Studies</a></li>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="page-lead">
|
<div class="page-lead">
|
||||||
<h1>{% block title %}{% endblock %}</h1>
|
<h1 class="text-center">{% block title %}{% endblock %}</h1>
|
||||||
<p class="lead">{% block description %}{% endblock %}</p>
|
<p class="lead text-center">{% block description %}{% endblock %}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
</div><!-- /.container -->
|
</div><!-- /.container -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
{% extends "map/base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<style>
|
<style>
|
||||||
body {
|
|
||||||
padding-top: 50px;
|
|
||||||
}
|
|
||||||
.jumbo {
|
.jumbo {
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 64px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -19,12 +16,10 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
{% include "map/_nav.html" %}
|
|
||||||
|
|
||||||
<div class="jumbo">
|
<div class="jumbo">
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
</div><!-- /.container -->
|
</div><!-- /.container -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
117
apps/map/templates/map/detail.html
Normal file
117
apps/map/templates/map/detail.html
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
{% extends "base_with_jumbo.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load compress %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load leaflet_tags %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<script src="bundle.js"></script>
|
||||||
|
</head>
|
||||||
|
{% block content %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row" style="background-color: #e3f3fd;">
|
||||||
|
<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>
|
||||||
|
<div style="margin-top:70px;padding:0 20px;">
|
||||||
|
<h1>{{case_study.entry_name}}</h1>
|
||||||
|
<p>{{case_study.synopsis}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix">
|
||||||
|
<div style="margin-left:20px;">
|
||||||
|
<span class="badge badge-pill bg-dark">{{case_study.get_sector_of_economy_display}}</span>
|
||||||
|
{% if case_study.positive_or_negative == "P" %}
|
||||||
|
<span class="badge badge-pill bg-success">{{case_study.get_positive_or_negative_display}}</span>
|
||||||
|
{% elif case_study.positive_or_negative == "N"%}
|
||||||
|
<span class="badge badge-pill bg-danger">{{case_study.get_positive_or_negative_display}}</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="badge badge-pill bg-info">{{case_study.country.name}}</span>
|
||||||
|
</br>
|
||||||
|
<small class="text-muted">Created {{case_study.date_created|naturaltime}} by <i>{{case_study.author.}}</i></small>
|
||||||
|
</div>
|
||||||
|
<a class="btn btn-primary btn-lg float-right" href="#" role="button">Get Involved</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="embed-responsive embed-responsive-16by9">
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ScMzIvxBSi4?rel=0&showinfo=0" frameborder="0" allowfullscreen></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" style="padding-top:30px;">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div id="accordion" role="tablist">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header" role="tab" id="headingOne">
|
||||||
|
<h5 class="mb-0">
|
||||||
|
<a data-toggle="collapse" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
||||||
|
{% trans "Full Description" %}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="collapseOne" class="collapse show" role="tabpanel" aria-labelledby="headingOne" data-parent="#accordion">
|
||||||
|
<div class="card-body">
|
||||||
|
{{case_study.full_description}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header" role="tab" id="headingTwo">
|
||||||
|
<h5 class="mb-0">
|
||||||
|
<a class="collapsed" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||||
|
{% trans "Community Voices" %}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div id="collapseTwo" class="collapse" role="tabpanel" aria-labelledby="headingTwo" data-parent="#accordion">
|
||||||
|
<div class="card-body">
|
||||||
|
{{case_study.community_voices}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
{% trans "Factbar" %}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
{% if case_study.area_of_land %}
|
||||||
|
<li class="list-group-item">{% trans "Approximate land area"%}: {{case_study.area_of_land}} km²</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
Attached Files
|
||||||
|
</div>
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="#">File One</a></br>
|
||||||
|
<small class="text-muted">Uploaded one month ago</small>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="#">File Two</a></br>
|
||||||
|
<small class="text-muted">Uploaded 3 mins ago</small>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="footer text-center">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<span class="text-muted">Ojuso x Yansa</span>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
{% endblock %}
|
||||||
|
</html>
|
@ -1,4 +1,4 @@
|
|||||||
{% extends "map/base_with_container.html" %}
|
{% extends "base_page.html" %}
|
||||||
{% load compress %}
|
{% load compress %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
@ -21,4 +21,14 @@
|
|||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{% leaflet_js %}
|
{% leaflet_js %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
YourGeometryField = L.GeometryField.extend({
|
||||||
|
addTo: function (map) {
|
||||||
|
L.GeometryField.prototype.addTo.call(this, map);
|
||||||
|
// Customize map for field
|
||||||
|
console.log(this);
|
||||||
|
},
|
||||||
|
// See GeometryField source (static/leaflet/leaflet.forms.js) to override more stuff...
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
47
apps/map/templates/map/how_much_time.html
Normal file
47
apps/map/templates/map/how_much_time.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load compress %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
{{ block.super }}
|
||||||
|
<style>
|
||||||
|
a.btn-jumbo {
|
||||||
|
color: navy;
|
||||||
|
width:320px;
|
||||||
|
height:240px;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 5px;
|
||||||
|
white-space: normal;
|
||||||
|
line-height:55px;
|
||||||
|
padding:80px 20px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
a.btn-jumbo > * {
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
line-height:20px;
|
||||||
|
}
|
||||||
|
div.btn-jumbo-group {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "How much time do you have?" %}{% endblock %}
|
||||||
|
{% block description %}
|
||||||
|
{% trans "A complete picture is always more helpful but sometimes you don't have the time" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="btn-jumbo-group">
|
||||||
|
<a class="btn btn-jumbo bg-warning" href="{% url 'long-form' %}" role="button">
|
||||||
|
<h2>20+ Minutes</h2>
|
||||||
|
<p>Full Form (Preferred)</p>
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-jumbo bg-success" href="{% url 'short-form' %}" role="button">
|
||||||
|
<h2>5-10 Minutes</h2>
|
||||||
|
<p>Express Form</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -1,6 +1,5 @@
|
|||||||
{% extends "map/base_with_jumbo.html" %}
|
{% extends "base_with_jumbo.html" %}
|
||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
{% load compress %}
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load leaflet_tags %}
|
{% load leaflet_tags %}
|
||||||
|
|
||||||
@ -46,9 +45,9 @@
|
|||||||
onEachFeature: function (feature, layer) {
|
onEachFeature: function (feature, layer) {
|
||||||
var modalname = "case-study-"+feature.id
|
var modalname = "case-study-"+feature.id
|
||||||
layer.bindPopup(
|
layer.bindPopup(
|
||||||
"<h3>"+feature.properties.project_name+"</h3>"+
|
"<p>"+feature.properties.entry_name+"</p>"+
|
||||||
"<button type='button' class='btn btn-primary btn-block' data-toggle='modal' data-target='#"+modalname+"'>"
|
"<a class='btn btn-primary' href='case-study/"+feature.properties.slug+"' role='button'>"
|
||||||
+"{% trans "Quick View" %}"+"</button>"
|
+"{% trans "View" %}"+"</a>"
|
||||||
);
|
);
|
||||||
var modal = create(
|
var modal = create(
|
||||||
"<div class='modal fade' id='"+modalname+"' tabindex='-1' role='dialog' aria-labelledby='"+modalname+"-label'>"+
|
"<div class='modal fade' id='"+modalname+"' tabindex='-1' role='dialog' aria-labelledby='"+modalname+"-label'>"+
|
||||||
|
@ -5,9 +5,10 @@ from .models import CaseStudy
|
|||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', views.index, name='index'),
|
url(r'^$', views.Map.as_view(), name='index'),
|
||||||
url(r'^data.geojson$',
|
url(r'^data.geojson$', GeoJSONLayerView.as_view(model=CaseStudy, geometry_field='location'), name='data'),
|
||||||
GeoJSONLayerView.as_view(model=CaseStudy, geometry_field='location'),
|
url(r'^case-study/create/?$', views.Create.as_view(), name="create"),
|
||||||
name='data'),
|
url(r'^case-study/create/short/?$', views.ShortForm.as_view(), name='short-form'),
|
||||||
url(r'^case-study/add', views.form, name='form')
|
url(r'^case-study/create/long/?$', views.LongForm.as_view(), name='long-form'),
|
||||||
|
url(r'^case-study/(?P<slug>[-\w]+)/?$', views.CaseStudyDetail.as_view(), name='detail')
|
||||||
]
|
]
|
||||||
|
@ -1,12 +1,35 @@
|
|||||||
from django.shortcuts import render
|
from django.views.generic import DetailView
|
||||||
|
from django.views.generic.base import TemplateView
|
||||||
from .forms import CaseStudyForm
|
from django.views.generic.edit import FormView
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from .models import CaseStudy
|
||||||
|
from .forms import ShortCaseStudyForm, LongCaseStudyForm
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
class Map(TemplateView):
|
||||||
return render(request, 'map/index.html')
|
template_name = "map/index.html"
|
||||||
|
|
||||||
|
|
||||||
def form(request):
|
class Create(LoginRequiredMixin, TemplateView):
|
||||||
form = CaseStudyForm
|
template_name = "map/how_much_time.html"
|
||||||
return render(request, 'map/form.html', {'form': form})
|
|
||||||
|
|
||||||
|
class BaseForm(LoginRequiredMixin, FormView):
|
||||||
|
"""This is the base class for the short and long forms. It handles any shared logic between the two subclasses."""
|
||||||
|
template_name = 'map/form.html'
|
||||||
|
|
||||||
|
|
||||||
|
class ShortForm(BaseForm):
|
||||||
|
"""Here, we use the short version of the form."""
|
||||||
|
form_class = ShortCaseStudyForm
|
||||||
|
|
||||||
|
|
||||||
|
class LongForm(BaseForm):
|
||||||
|
"""Here, we use the long version of the form."""
|
||||||
|
form_class = LongCaseStudyForm
|
||||||
|
|
||||||
|
|
||||||
|
class CaseStudyDetail(DetailView):
|
||||||
|
template_name = "map/detail.html"
|
||||||
|
model = CaseStudy
|
||||||
|
context_object_name = "case_study"
|
||||||
|
0
apps/profiles/__init__.py
Normal file
0
apps/profiles/__init__.py
Normal file
3
apps/profiles/admin.py
Normal file
3
apps/profiles/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
apps/profiles/apps.py
Normal file
5
apps/profiles/apps.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ProfilesConfig(AppConfig):
|
||||||
|
name = 'profiles'
|
0
apps/profiles/migrations/__init__.py
Normal file
0
apps/profiles/migrations/__init__.py
Normal file
3
apps/profiles/models.py
Normal file
3
apps/profiles/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
2
apps/profiles/templates/profiles/profile.html
Normal file
2
apps/profiles/templates/profiles/profile.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
Profile page
|
3
apps/profiles/tests.py
Normal file
3
apps/profiles/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
7
apps/profiles/urls.py
Normal file
7
apps/profiles/urls.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', views.Profile.as_view(), name='profile'),
|
||||||
|
]
|
5
apps/profiles/views.py
Normal file
5
apps/profiles/views.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from django.views.generic.base import TemplateView
|
||||||
|
|
||||||
|
|
||||||
|
class Profile(TemplateView):
|
||||||
|
template_name = "profiles/profile.html"
|
@ -6,11 +6,13 @@ services:
|
|||||||
- db:db
|
- db:db
|
||||||
- cache:cache
|
- cache:cache
|
||||||
volumes:
|
volumes:
|
||||||
|
- ./apps:/app/apps
|
||||||
|
- ./ojusomap:/app/ojusomap
|
||||||
- /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:
|
||||||
- ./environment
|
- ./local.env
|
||||||
command: /bin/sh -c "python3 manage.py migrate && python3 manage.py collectstatic --noinput && gunicorn --bind 0.0.0.0:8000 ojusomap.wsgi"
|
command: /bin/sh -c "python3 manage.py migrate && DEBUG=1 python3 manage.py collectstatic --noinput && gunicorn --bind 0.0.0.0:8000 ojusomap.wsgi"
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mdillon/postgis:9.6-alpine
|
image: mdillon/postgis:9.6-alpine
|
||||||
|
@ -1,45 +1 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash
|
||||||
export DEBUG=0
|
|
||||||
export ALLOWED_HOSTS=map.ojuso.org
|
|
||||||
export DATABASE_HOST=localhost
|
|
||||||
export DATABASE_NAME=postgres
|
|
||||||
export DATABASE_PASSWORD=2xXKKS9zdrBX9QJaV5Z5NPTiiW8LtTiR4vAGSACddqFTrBdhgwZHKYnLqjJedAi3
|
|
||||||
export EMAIL_HOST=mail.gandi.net
|
|
||||||
export EMAIL_HOST_USER=admin@ojuso.org
|
|
||||||
export EMAIL_HOST_PASSWORD=QN7yosrnch1le474H56mesVR1SRw6sfO3izJDZnJ6T62Cj9I57CplW6UYZY6VXsq7lLr868bIK3kSXGyWiSrAyWK
|
|
||||||
export EMAIL_PORT=587
|
|
||||||
export EMAIL_USE_TLS=1
|
|
||||||
export SECRET_KEY=a3DfjSmWkSffsPscRscqaxGv6HsBN8VKL8Q4EU4QcdEckB8scogrMP4tv7Eo7LZw
|
|
||||||
export SERVER_EMAIL=Ojuso\ Platform\ Notification\ \<admin@ojuso.org\>
|
|
||||||
export POSTGRES_USER=postgres
|
|
||||||
export POSTGRES_PASSWORD=2xXKKS9zdrBX9QJaV5Z5NPTiiW8LtTiR4vAGSACddqFTrBdhgwZHKYnLqjJedAi3
|
|
||||||
export DISCOURSE_DB_SOCKET=/var/run/postgresql
|
|
||||||
export DISCOURSE_DEVELOPER_EMAILS=admin@ojuso.org
|
|
||||||
export DISCOURSE_HOSTNAME=forum.ojuso.org
|
|
||||||
export DISCOURSE_SMTP_ADDRESS=mail.gandi.net
|
|
||||||
export DISCOURSE_SMTP_PASSWORD=QN7yosrnch1le474H56mesVR1SRw6sfO3izJDZnJ6T62Cj9I57CplW6UYZY6VXsq7lLr868bIK3kSXGyWiSrAyWK
|
|
||||||
export DISCOURSE_SMTP_PORT=587
|
|
||||||
export DISCOURSE_SMTP_USER_NAME=admin@ojuso.org
|
|
||||||
export DOCKER_HOST_IP=172.17.0.1
|
|
||||||
export LANG=en_US.UTF-8
|
|
||||||
export RAILS_ENV=production
|
|
||||||
export RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000
|
|
||||||
export RUBY_GC_HEAP_INIT_SLOTS=400000
|
|
||||||
export RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5
|
|
||||||
export RUBY_GLOBAL_METHOD_CACHE_SIZE=131072
|
|
||||||
export UNICORN_SIDEKIQS=1
|
|
||||||
export UNICORN_WORKERS=4
|
|
||||||
export WEBLATE_DEBUG=0
|
|
||||||
export WEBLATE_LOGLEVEL=DEBUG
|
|
||||||
export WEBLATE_SITE_TITLE=Ojuso\ Weblate
|
|
||||||
export WEBLATE_ADMIN_NAME=Weblate\ Admin
|
|
||||||
export WEBLATE_ADMIN_EMAIL=admin@ojuso.org
|
|
||||||
export WEBLATE_ADMIN_PASSWORD=zPFPtHLsRRFAAcApeGd23aV6Hg66KpTkWs2becsMMoL9dTeKLNt3PfH5Bzhyna8q
|
|
||||||
export WEBLATE_SERVER_EMAIL=noreply@ojuso.org
|
|
||||||
export WEBLATE_DEFAULT_FROM_EMAIL=noreply@ojuso.org
|
|
||||||
export WEBLATE_ALLOWED_HOSTS=*
|
|
||||||
export WEBLATE_REGISTRATION_OPEN=1
|
|
||||||
export WEBLATE_GITHUB_USERNAME=livmackintosh
|
|
||||||
export WEBLATE_EMAIL_HOST=mail.gandi.net
|
|
||||||
export WEBLATE_EMAIL_USER=admin@ojuso.org
|
|
||||||
export WEBLATE_EMAIL_PASSWORD=QN7yosrnch1le474H56mesVR1SRw6sfO3izJDZnJ6T62Cj9I57CplW6UYZY6VXsq7lLr868bIK3kSXGyWiSrAyWK
|
|
||||||
|
17
local.env
Normal file
17
local.env
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Django Configuration
|
||||||
|
DEBUG=1
|
||||||
|
ALLOWED_HOSTS=localhost
|
||||||
|
DATABASE_HOST=db
|
||||||
|
DATABASE_NAME=postgres
|
||||||
|
DATABASE_PASSWORD=postgres
|
||||||
|
EMAIL_HOST=mail
|
||||||
|
EMAIL_HOST_USER=admin@ojuso.org
|
||||||
|
EMAIL_HOST_PASSWORD=
|
||||||
|
EMAIL_PORT=1025
|
||||||
|
EMAIL_USE_TLS=0
|
||||||
|
SECRET_KEY=kZQPK56roVhFkwPqFF9xZoHFlw38uVuXNCjtXor6FRiieiYds9ltuM6oZeZ75CEe
|
||||||
|
SERVER_EMAIL=Ojuso Platform Notification <livvy@base.nu>
|
||||||
|
|
||||||
|
# Postgres Database Setup
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=postgres
|
41
local.yml
Normal file
41
local.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
map:
|
||||||
|
build: .
|
||||||
|
links:
|
||||||
|
- db:db
|
||||||
|
- cache:cache
|
||||||
|
- mailhog:mail
|
||||||
|
volumes:
|
||||||
|
- .containers/map/static:/app/static
|
||||||
|
- .containers/map/gunicorn.sock:/app/gunicorn.sock
|
||||||
|
- ./apps:/app/apps
|
||||||
|
- ./ojusomap:/app/ojusomap
|
||||||
|
- ./support:/app/support
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
env_file:
|
||||||
|
- ./local.env
|
||||||
|
command: /bin/sh -c "python3 manage.py collectstatic --noinput ; python3 manage.py runserver 0.0.0.0:8000"
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mdillon/postgis:9.6-alpine
|
||||||
|
volumes:
|
||||||
|
- .containers/db:/var/lib/postgresql/data
|
||||||
|
- ./support/postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5432:5432"
|
||||||
|
env_file:
|
||||||
|
- ./local.env
|
||||||
|
|
||||||
|
mailhog:
|
||||||
|
image: mailhog/mailhog
|
||||||
|
ports:
|
||||||
|
- 1025:1025
|
||||||
|
- 8025:8025
|
||||||
|
|
||||||
|
cache:
|
||||||
|
image: memcached:1.4
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
weblate-data:
|
@ -35,12 +35,18 @@ ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split()
|
|||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
'apps.contact',
|
||||||
'apps.map',
|
'apps.map',
|
||||||
|
'apps.profiles',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
|
'registration',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.humanize',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.sites',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
|
'whitenoise.runserver_nostatic',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.gis',
|
'django.contrib.gis',
|
||||||
'bootstrap3',
|
'bootstrap3',
|
||||||
@ -48,13 +54,16 @@ INSTALLED_APPS = [
|
|||||||
'compressor',
|
'compressor',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
|
'envelope',
|
||||||
'leaflet',
|
'leaflet',
|
||||||
|
'moderation',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'rest_framework_gis',
|
'rest_framework_gis',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.locale.LocaleMiddleware',
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@ -66,10 +75,12 @@ MIDDLEWARE = [
|
|||||||
|
|
||||||
ROOT_URLCONF = 'ojusomap.urls'
|
ROOT_URLCONF = 'ojusomap.urls'
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [],
|
'DIRS': [os.path.join(BASE_DIR, 'ojusomap/templates/')],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
@ -95,7 +106,6 @@ EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER')
|
|||||||
EMAIL_PORT = os.getenv('EMAIL_PORT', 25)
|
EMAIL_PORT = os.getenv('EMAIL_PORT', 25)
|
||||||
EMAIL_USE_TLS = bool(int(os.getenv('EMAIL_USE_TLS', False)))
|
EMAIL_USE_TLS = bool(int(os.getenv('EMAIL_USE_TLS', False)))
|
||||||
EMAIL_SUBJECT_PREFIX = "Ojuso Platform"
|
EMAIL_SUBJECT_PREFIX = "Ojuso Platform"
|
||||||
|
|
||||||
SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'root@localhost')
|
SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'root@localhost')
|
||||||
|
|
||||||
|
|
||||||
@ -131,6 +141,8 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Registration (Redux)
|
||||||
|
ACCOUNT_ACTIVATION_DAYS = 3
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||||
@ -163,10 +175,9 @@ STATIC_URL = os.getenv("STATIC_URL", '/static/')
|
|||||||
STATICFILES_FINDERS = [
|
STATICFILES_FINDERS = [
|
||||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||||
'compressor.finders.CompressorFinder',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
# https://docs.djangoproject.com/en/1.11/topics/cache/
|
# https://docs.djangoproject.com/en/1.11/topics/cache/
|
||||||
@ -204,7 +215,7 @@ REST_FRAMEWORK = {
|
|||||||
# Django Crispy Forms
|
# Django Crispy Forms
|
||||||
# http://django-crispy-forms.readthedocs.io/en/latest/
|
# http://django-crispy-forms.readthedocs.io/en/latest/
|
||||||
|
|
||||||
CRISPY_TEMPLATE_PACK = 'bootstrap3'
|
CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
||||||
|
|
||||||
# Django-Leaflet
|
# Django-Leaflet
|
||||||
# https://django-leaflet.readthedocs.io/en/latest/
|
# https://django-leaflet.readthedocs.io/en/latest/
|
||||||
|
10
ojusomap/templates/400.html
Normal file
10
ojusomap/templates/400.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
9
ojusomap/templates/403.html
Normal file
9
ojusomap/templates/403.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends 'base_page.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Shucks.
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block description %}
|
||||||
|
Looks like you're not supposed to be here.
|
||||||
|
{% endblock %}
|
9
ojusomap/templates/404.html
Normal file
9
ojusomap/templates/404.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends 'base_page.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Shucks.
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block description %}
|
||||||
|
You've taken a wrong turn and we can't find the page you're looking for.
|
||||||
|
{% endblock %}
|
9
ojusomap/templates/500.html
Normal file
9
ojusomap/templates/500.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends 'base_page.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Shucks.
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block description %}
|
||||||
|
An unknown server error occurred. Sorry about that.
|
||||||
|
{% endblock %}
|
66
ojusomap/templates/base.html
Normal file
66
ojusomap/templates/base.html
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
{% spaceless %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load leaflet_tags %}
|
||||||
|
{% load static %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{% block page_title %}Ojuso{% endblock %}</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<script src="{% static 'map/bundle.js'%}"></script>
|
||||||
|
|
||||||
|
{# Additional Stylesheets #}
|
||||||
|
{% block stylesheets %}
|
||||||
|
<style>
|
||||||
|
.navbar-brand {padding: 5px 15px;}
|
||||||
|
.navbar-brand > img {height: 40px;}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<a class="navbar-brand" href="{% url 'index' %}">
|
||||||
|
<img src="{% static 'map/images/ojuso-logo-black.png' %}" height="40px"/>
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="#">Map <span class="sr-only">(current)</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Policy</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Contact</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">FAQ</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<span>{{user}}</span>
|
||||||
|
<a class="btn btn-primary" href={% url 'auth_logout' %}>Logout</a>
|
||||||
|
{% else %}
|
||||||
|
<a style="margin: 5px;" class="btn btn-primary" href={% url 'auth_login' %}>Login</a>
|
||||||
|
<a style="margin: 5px;" class="btn btn-info" href={% url 'registration_register' %}>Register</a>
|
||||||
|
{% endif %}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
{# CDN Javascript #}
|
||||||
|
<script src="//code.jquery.com/jquery-3.2.1.min.js"
|
||||||
|
integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f"
|
||||||
|
crossorigin="anonymous">
|
||||||
|
</script>
|
||||||
|
{% block scripts %}{% endblock %}
|
||||||
|
</html>
|
||||||
|
{% endspaceless %}
|
27
ojusomap/templates/base_page.html
Normal file
27
ojusomap/templates/base_page.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
{{ block.super }}
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.page-lead {
|
||||||
|
padding: 40px 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="page-lead">
|
||||||
|
<h1 class="text-center">{% block title %}{% endblock %}</h1>
|
||||||
|
<p class="lead text-center">{% block description %}{% endblock %}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</div><!-- /.container -->
|
||||||
|
{% endblock %}
|
25
ojusomap/templates/base_with_jumbo.html
Normal file
25
ojusomap/templates/base_with_jumbo.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
{{ block.super }}
|
||||||
|
<style>
|
||||||
|
.jumbo {
|
||||||
|
height: calc(100% - 64px);
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<div class="jumbo">
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</div><!-- /.container -->
|
||||||
|
{% endblock %}
|
1
ojusomap/templates/registration/activate.html
Normal file
1
ojusomap/templates/registration/activate.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% extends 'base_page.html' %}
|
1
ojusomap/templates/registration/activation_complete.html
Normal file
1
ojusomap/templates/registration/activation_complete.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% extends 'base_page.html' %}
|
10
ojusomap/templates/registration/activation_email.html
Normal file
10
ojusomap/templates/registration/activation_email.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends 'base_email.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<div align="left">
|
||||||
|
{{user}},<br><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>
|
||||||
|
See you on the activist trail!<br><br>
|
||||||
|
- Animal Rights Map
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1 @@
|
|||||||
|
Activate your Ojuso Identity account.
|
24
ojusomap/templates/registration/login.html
Normal file
24
ojusomap/templates/registration/login.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load envelope_tags %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block page_title %}{% trans "Login"%} | Ojuso{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container" style="max-width:520px;">
|
||||||
|
<div class="page-lead">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<p class="lead">{% trans "Welcome!" %}</p>
|
||||||
|
</div>
|
||||||
|
{% bootstrap_messages %}
|
||||||
|
<form action="{% url 'auth_login' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% antispam_fields %}
|
||||||
|
{{form|crispy}}
|
||||||
|
<p><a href="{% url 'auth_password_reset' %}">{% trans "Lost password?" %}</a></p>
|
||||||
|
<input class="btn btn-success pull-right" type="submit" name="submit" value="{% trans 'Login' %}"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
11
ojusomap/templates/registration/logout.html
Normal file
11
ojusomap/templates/registration/logout.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load envelope_tags %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block page_name %}Registration{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<p class="text-center">{% trans "You've just been logged out." %} <a href="{% url 'auth_login' %}">{% trans "Click here to login again." %}</p>
|
||||||
|
{% endblock %}
|
14
ojusomap/templates/registration/password_reset_email.html
Normal file
14
ojusomap/templates/registration/password_reset_email.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{% load i18n %}{% autoescape off %}
|
||||||
|
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
|
||||||
|
|
||||||
|
{% trans "Please go to the following page and choose a new password:" %}
|
||||||
|
{% block reset_link %}
|
||||||
|
{{ protocol }}://{{ domain }}{% url 'auth_password_reset_confirm' uidb64=uid token=token %}
|
||||||
|
{% endblock %}
|
||||||
|
{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}
|
||||||
|
|
||||||
|
{% trans "Thanks for using our site!" %}
|
||||||
|
|
||||||
|
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
|
||||||
|
|
||||||
|
{% endautoescape %}
|
12
ojusomap/templates/registration/registration_closed.html
Normal file
12
ojusomap/templates/registration/registration_closed.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% block page_name %}Registration{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-lead">
|
||||||
|
<h2>Registration</h2>
|
||||||
|
<p class="lead">Account registration is currently closed. Come back soon!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
22
ojusomap/templates/registration/registration_form.html
Normal file
22
ojusomap/templates/registration/registration_form.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{% extends "base_page.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load envelope_tags %}
|
||||||
|
|
||||||
|
{% block page_name %}Registration{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container" style="max-width:520px;">
|
||||||
|
<div class="page-lead">
|
||||||
|
<h2>Registration</h2>
|
||||||
|
<p class="lead">Create your account and get active!</p>
|
||||||
|
</div>
|
||||||
|
{% bootstrap_messages %}
|
||||||
|
<form action="{% url 'registration_register' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% antispam_fields %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<input class="btn btn-success pull-right" type="submit" name"submit" value"Register"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -14,6 +14,7 @@ Including another URLconf
|
|||||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
|
from django.urls import reverse
|
||||||
from django.conf.urls.i18n import i18n_patterns
|
from django.conf.urls.i18n import i18n_patterns
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -51,8 +52,12 @@ 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'^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")
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += i18n_patterns(
|
urlpatterns += i18n_patterns(
|
||||||
|
url(r'^accounts/profile/', include('apps.profiles.urls')),
|
||||||
|
# url(r'^accounts/logout/?$', include('django.contrib.auth.views.logout'), {'next_page': '/'}),
|
||||||
|
url(r'^accounts/', include('registration.backends.default.urls')),
|
||||||
url(r'', include('apps.map.urls'), name="map"),
|
url(r'', include('apps.map.urls'), name="map"),
|
||||||
)
|
)
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
Django==1.10.7
|
brotlipy==0.7.0
|
||||||
|
Django==1.11.6
|
||||||
django-appconf==1.0.2
|
django-appconf==1.0.2
|
||||||
django-bootstrap3==8.2.3
|
django-bootstrap3==8.2.3
|
||||||
|
django-braces==1.11.0
|
||||||
django-cas-server==0.8.0
|
django-cas-server==0.8.0
|
||||||
django-compressor==2.1.1
|
django-compressor==2.1.1
|
||||||
django-countries==4.5
|
django-countries==4.5
|
||||||
django-crispy-forms==1.6.1
|
django-crispy-forms==1.6.1
|
||||||
|
django-envelope==1.3
|
||||||
django-extensions==1.7.9
|
django-extensions==1.7.9
|
||||||
django-geojson==2.10.0
|
django-geojson==2.10.0
|
||||||
django-leaflet==0.22.0
|
#django-leaflet==0.22.0
|
||||||
|
-e git://github.com/makinacorpus/django-leaflet.git@a43acc5fed6674b413a6fab0feeb7c44e67c2ca8#egg=django-leaflet
|
||||||
|
django-moderation==0.5.0
|
||||||
|
django-registration-redux==1.6
|
||||||
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
|
||||||
@ -25,3 +31,4 @@ requests==2.14.2
|
|||||||
requests-futures==0.9.7
|
requests-futures==0.9.7
|
||||||
rjsmin==1.0.12
|
rjsmin==1.0.12
|
||||||
six==1.10.0
|
six==1.10.0
|
||||||
|
whitenoise==3.3.1
|
||||||
|
Loading…
Reference in New Issue
Block a user