diff --git a/opentech/people/templates/people/includes/person_listing.html b/opentech/people/templates/people/includes/person_listing.html new file mode 100644 index 0000000000000000000000000000000000000000..9ec5a19cbe6311e9c0e4bb839555fb5ea021c83e --- /dev/null +++ b/opentech/people/templates/people/includes/person_listing.html @@ -0,0 +1,7 @@ +<article class="person"> + <h2><a href="{% pageurl person %}">{{ person.first_name }} {{ person.last_name }}</a></h2> + + {% if person.listing_summary or person.introduction %} + <p>{{ person.listing_summary|default:person.introduction }}</p> + {% endif %} +</article> diff --git a/opentech/public/funds/__init__.py b/opentech/public/funds/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2d9aa6a15b3cc680aa74c46b62a765839603a625 --- /dev/null +++ b/opentech/public/funds/__init__.py @@ -0,0 +1 @@ +default_app_config = 'opentech.public.funds.apps.FundsConfig' diff --git a/opentech/public/funds/admin.py b/opentech/public/funds/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..4185d360e9a725a190ddfd9b8cce8aeb0df64cc3 --- /dev/null +++ b/opentech/public/funds/admin.py @@ -0,0 +1,3 @@ +# from django.contrib import admin + +# Register your models here. diff --git a/opentech/public/funds/apps.py b/opentech/public/funds/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..5c980bcdf7583884f254151716ab6e45a87c56bc --- /dev/null +++ b/opentech/public/funds/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class FundsConfig(AppConfig): + name = 'opentech.public.funds' + label = 'public_funds' diff --git a/opentech/public/funds/blocks.py b/opentech/public/funds/blocks.py new file mode 100644 index 0000000000000000000000000000000000000000..e6273c47d636680c1f7b38ee4608511f16a7e6aa --- /dev/null +++ b/opentech/public/funds/blocks.py @@ -0,0 +1,24 @@ +from wagtail.wagtailcore.blocks import StaticBlock + +from opentech.public.utils.blocks import StoryBlock + + +class ProjectsBlock(StaticBlock): + class Meta: + icon = 'grip' + label = 'List of Projects funded' + admin_text = f'{label}: Will include the list of projects under this fund.' + template = 'public_funds/blocks/related_projects.html' + + +class ReviewersBlock(StaticBlock): + class Meta: + icon = 'grip' + label = 'List of fund Reviewers' + admin_text = f'{label}: Will include the list of reviewers for this fund.' + template = 'public_funds/blocks/related_reviewers.html' + + +class FundBlock(StoryBlock): + project_list = ProjectsBlock() + reviewer_list = ReviewersBlock() diff --git a/opentech/public/funds/migrations/0001_initial.py b/opentech/public/funds/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..5cab88a42287d90cf2fffadd5b55930b9aa7fbfc --- /dev/null +++ b/opentech/public/funds/migrations/0001_initial.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-09 11:20 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.wagtailcore.blocks +import wagtail.wagtailcore.fields +import wagtail.wagtaildocs.blocks +import wagtail.wagtailembeds.blocks +import wagtail.wagtailimages.blocks +import wagtail.wagtailsnippets.blocks + +import opentech + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0040_page_draft_title'), + ('images', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='FundIndex', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), + ('social_text', models.CharField(blank=True, max_length=255)), + ('listing_title', models.CharField(blank=True, help_text='Override the page title used when this page appears in listings', max_length=255)), + ('listing_summary', models.CharField(blank=True, help_text="The text summary used when this page appears in listings. It's also used as the description for search engines if the 'Search description' field above is not defined.", max_length=255)), + ('header_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')), + ('listing_image', models.ForeignKey(blank=True, help_text='Choose the image you wish to be displayed when this page appears in listings', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')), + ('social_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='FundPage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), + ('social_text', models.CharField(blank=True, max_length=255)), + ('listing_title', models.CharField(blank=True, help_text='Override the page title used when this page appears in listings', max_length=255)), + ('listing_summary', models.CharField(blank=True, help_text="The text summary used when this page appears in listings. It's also used as the description for search engines if the 'Search description' field above is not defined.", max_length=255)), + ('introduction', models.TextField(blank=True)), + ('body', wagtail.wagtailcore.fields.StreamField((('heading', wagtail.wagtailcore.blocks.CharBlock(classname='full title', icon='title')), ('paragraph', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('caption', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('quote', wagtail.wagtailcore.blocks.StructBlock((('quote', wagtail.wagtailcore.blocks.CharBlock(classname='title')), ('attribution', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('job_title', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('embed', wagtail.wagtailembeds.blocks.EmbedBlock()), ('call_to_action', wagtail.wagtailsnippets.blocks.SnippetChooserBlock('utils.CallToActionSnippet', template='blocks/call_to_action_block.html')), ('document', wagtail.wagtailcore.blocks.StructBlock((('document', wagtail.wagtaildocs.blocks.DocumentChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('project_list', opentech.public.funds.blocks.ProjectsBlock()), ('reviewer_list', opentech.public.funds.blocks.ReviewersBlock())))), + ('fund_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.Page')), + ('header_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')), + ('listing_image', models.ForeignKey(blank=True, help_text='Choose the image you wish to be displayed when this page appears in listings', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')), + ('social_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page', models.Model), + ), + ] diff --git a/opentech/public/funds/migrations/__init__.py b/opentech/public/funds/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opentech/public/funds/models.py b/opentech/public/funds/models.py new file mode 100644 index 0000000000000000000000000000000000000000..c5b012db1a3d44ee8c7b50f9714d72da77918257 --- /dev/null +++ b/opentech/public/funds/models.py @@ -0,0 +1,57 @@ +from django.conf import settings +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models + +from wagtail.wagtailadmin.edit_handlers import ( + FieldPanel, + PageChooserPanel, + StreamFieldPanel, +) +from wagtail.wagtailcore.fields import StreamField + +from opentech.public.utils.models import BasePage + +from .blocks import FundBlock + + +class FundPage(BasePage): + subpage_types = [] + parent_page_types = ['FundIndex'] + + introduction = models.TextField(blank=True) + fund_type = models.ForeignKey( + 'wagtailcore.Page', + blank=True, + null=True, + on_delete=models.SET_NULL, + related_name='+', + ) + body = StreamField(FundBlock()) + + content_panels = BasePage.content_panels + [ + FieldPanel('introduction'), + PageChooserPanel('fund_type', 'funds.FundType'), + StreamFieldPanel('body'), + ] + + +class FundIndex(BasePage): + subpage_types = ['FundPage'] + parent_page_types = ['home.HomePage'] + + def get_context(self, request, *args, **kwargs): + funds = FundPage.objects.live().public().descendant_of(self) + + # Pagination + page = request.GET.get('page', 1) + paginator = Paginator(funds, settings.DEFAULT_PER_PAGE) + try: + news = paginator.page(page) + except PageNotAnInteger: + news = paginator.page(1) + except EmptyPage: + news = paginator.page(paginator.num_pages) + + context = super().get_context(request, *args, **kwargs) + context.update(news=news) + return context diff --git a/opentech/public/funds/templates/public_funds/blocks/related_projects.html b/opentech/public/funds/templates/public_funds/blocks/related_projects.html new file mode 100644 index 0000000000000000000000000000000000000000..a1a791e991778058d2f07ecebd60687b2ad1444d --- /dev/null +++ b/opentech/public/funds/templates/public_funds/blocks/related_projects.html @@ -0,0 +1,3 @@ +{% for project in page.projects %} + {% include "public_funds/includes/project_listing.html" with project=project %} +{% endfor %} diff --git a/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html b/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html new file mode 100644 index 0000000000000000000000000000000000000000..fbb24ea53fcda8740a0a674ee0eac2823d5dd179 --- /dev/null +++ b/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html @@ -0,0 +1,3 @@ +{% for person in page.reviewers %} + {% include "person/includes/person_listing.html" with person=person %} +{% endfor %} diff --git a/opentech/public/funds/templates/public_funds/fund_index.html b/opentech/public/funds/templates/public_funds/fund_index.html new file mode 100644 index 0000000000000000000000000000000000000000..ce4f0b1db6ef2f27f9269c007d362c79d43b38d4 --- /dev/null +++ b/opentech/public/funds/templates/public_funds/fund_index.html @@ -0,0 +1 @@ +{% extends "standardpages/index_page.html" %} diff --git a/opentech/public/funds/templates/public_funds/fund_page.html b/opentech/public/funds/templates/public_funds/fund_page.html new file mode 100644 index 0000000000000000000000000000000000000000..7c6f6f51608f36eee2a489ef095097807322574e --- /dev/null +++ b/opentech/public/funds/templates/public_funds/fund_page.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} +{% load wagtailcore_tags wagtailimages_tags navigation_tags static %} + +{% block content %} + {% include "public_funds/includes/fund_apply_cta.html" with fund_type=page.fund_type.specific %} + <div class="wrapper wrapper--flex"> + <section class="section section--main"> + <h1>{{ page.title }}</h1> + <h5>{{ page.introduction }}</h5> + + {% include_block page.body %} + </section> + </div> + {% include "public_funds/includes/fund_apply_cta.html" with fund_type=page.fund_type.specific %} + {% include "includes/relatedcontent.html" with related_pages=page.related_pages.all %} +{% endblock %} diff --git a/opentech/public/funds/templates/public_funds/includes/fund_apply_cta.html b/opentech/public/funds/templates/public_funds/includes/fund_apply_cta.html new file mode 100644 index 0000000000000000000000000000000000000000..1f81aa425819a5ce32bce596c0833547d4009086 --- /dev/null +++ b/opentech/public/funds/templates/public_funds/includes/fund_apply_cta.html @@ -0,0 +1,18 @@ +{% load wagtailcore_tags i18n %} + +<div class="wrapper wrapper--flex"> + <div class="section section--apply-cta"> + {% if fund_type.deadline %} + <div class="deadline"> + {% trans "Next deadline" %}: {{ fund_type.deadline|date:"M j, Y" }} + </div> + <div class="apply-link"> + <a class="button" href="{% pageurl fund_type %}">{% trans "Apply for this fund" %}</a> + </div> + {% else %} + <div class="deadline"> + {% trans "CLOSED" %} + </div> + {% endif %} + </div> +</div> diff --git a/opentech/public/funds/templates/public_funds/includes/project_listing.html b/opentech/public/funds/templates/public_funds/includes/project_listing.html new file mode 100644 index 0000000000000000000000000000000000000000..0ff5422e2a71c5442863900d835cfbc15ba70eae --- /dev/null +++ b/opentech/public/funds/templates/public_funds/includes/project_listing.html @@ -0,0 +1 @@ +<p>A PROJECT</p> diff --git a/opentech/public/funds/tests.py b/opentech/public/funds/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..a79ca8be565f44aacce95bad20c1ee34d175ed20 --- /dev/null +++ b/opentech/public/funds/tests.py @@ -0,0 +1,3 @@ +# from django.test import TestCase + +# Create your tests here. diff --git a/opentech/public/funds/views.py b/opentech/public/funds/views.py new file mode 100644 index 0000000000000000000000000000000000000000..fd0e0449559b2e00e226cc9f96df7caed44172aa --- /dev/null +++ b/opentech/public/funds/views.py @@ -0,0 +1,3 @@ +# from django.shortcuts import render + +# Create your views here. diff --git a/opentech/public/people/templates/people/person_index_page.html b/opentech/public/people/templates/people/person_index_page.html index 873be5204e224b625139572257f885dca388005e..7d5f4d3a2c2ac5fb60f06e5e1ac632e0eb7012b4 100644 --- a/opentech/public/people/templates/people/person_index_page.html +++ b/opentech/public/people/templates/people/person_index_page.html @@ -13,13 +13,7 @@ <div class="container"> {% if people.paginator.count %} {% for person in people %} - <article class="person"> - <h2><a href="{% pageurl person %}">{{ person.first_name }} {{ person.last_name }}</a></h2> - - {% if person.listing_summary or person.introduction %} - <p>{{ person.listing_summary|default:person.introduction }}</p> - {% endif %} - </article> + {% include "people/includes/person_listing.html" with person=person %} {% endfor %} {% include "includes/pagination.html" with paginator_page=people %} diff --git a/opentech/settings/base.py b/opentech/settings/base.py index 2693c88cb6f15773507c3866d5e099a9c793f205..ced6888bc9e76d811695568ff455bf531c856afa 100644 --- a/opentech/settings/base.py +++ b/opentech/settings/base.py @@ -22,6 +22,7 @@ INSTALLED_APPS = [ 'opentech.public.esi', 'opentech.public.forms', + 'opentech.public.funds', 'opentech.public.home', 'opentech.public.navigation', 'opentech.public.news', diff --git a/opentech/templates/blocks/stream_block.html b/opentech/templates/blocks/stream_block.html index aa12d231f21b0b23a618942e32b387c21f10572e..2341b05106d47c549891d7f02bd7daae9d6f879a 100644 --- a/opentech/templates/blocks/stream_block.html +++ b/opentech/templates/blocks/stream_block.html @@ -1,7 +1,8 @@ +{% load wagtailcore_tags %} {% for block in value %} {% if block.block_type == 'heading' %} <h2>{{ block.value }}</h2> {% else %} - {{ block }} + {% include_block block %} {% endif %} {% endfor %}