diff --git a/opentech/apply/funds/models/submissions.py b/opentech/apply/funds/models/submissions.py index 53ea4608550ebb0c2d4747f3765b4eb18d6b7388..2c58f5edbb3da19238d14b9a92bd4f3f77b2b1b2 100644 --- a/opentech/apply/funds/models/submissions.py +++ b/opentech/apply/funds/models/submissions.py @@ -324,12 +324,6 @@ class ApplicationSubmission( def active(self): return self.status in active_statuses - @property - def last_edit(self): - # Best estimate of last edit - # TODO update when we have revisioning included - return self.activities.first() - def ensure_user_has_account(self): if self.user and self.user.is_authenticated: self.form_data['email'] = self.user.email diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html index b37da93f9f17b57b3a04fd942546b52ea64d0c19..1e8b7798b9e288d00b2ab967f6daf12b0ca95ecc 100644 --- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html +++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html @@ -58,7 +58,7 @@ <div> <h6 class="heading heading--submission-meta"> <span>Submitted: <strong>{{ object.submit_time.date }} by {{ object.user.get_full_name }}</strong></span> - <span>Last edited: <strong>{{ object.last_edit.timestamp.date }} by {{ object.last_edit.user.get_full_name }}</strong></span> + <span>Last edited: <strong>{{ object.live_revision.timestamp.date }} by {{ object.live_revision.author }}</strong></span> {% if request.user|has_edit_perm:object %} <a class="link link--edit-submission is-active" href="{% url 'funds:submissions:edit' object.id %}"> Edit diff --git a/opentech/public/funds/migrations/0009_allow_mailto_in_linkfield.py b/opentech/public/funds/migrations/0009_allow_mailto_in_linkfield.py new file mode 100644 index 0000000000000000000000000000000000000000..6e120532beeac6caad96b316f7a23fe41f354cc2 --- /dev/null +++ b/opentech/public/funds/migrations/0009_allow_mailto_in_linkfield.py @@ -0,0 +1,19 @@ +# Generated by Django 2.0.2 on 2018-08-31 20:25 + +from django.db import migrations, models +import opentech.public.funds.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('public_funds', '0008_recreate_pages'), + ] + + operations = [ + migrations.AlterField( + model_name='labpage', + name='lab_link', + field=models.CharField(blank=True, max_length=255, validators=[opentech.public.funds.models.MailToAndURLValidator()], verbose_name='External link'), + ), + ] diff --git a/opentech/public/funds/models.py b/opentech/public/funds/models.py index c2d7be7f5332f3e219184e589a3a94a0024d3bf5..ce7c61b4b2dfd33c8e9b5121b34141975e0e8448 100644 --- a/opentech/public/funds/models.py +++ b/opentech/public/funds/models.py @@ -1,7 +1,9 @@ from django.conf import settings from django.core.exceptions import ValidationError from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.core import validators from django.db import models +from django.utils.deconstruct import deconstructible from modelcluster.fields import ParentalKey from wagtail.admin.edit_handlers import ( @@ -112,6 +114,19 @@ class LabPageRelatedPage(RelatedPage): source_page = ParentalKey('LabPage', related_name='related_pages') +@deconstructible +class MailToAndURLValidator: + email_validator = validators.EmailValidator() + url_validator = validators.URLValidator() + + def __call__(self, value): + if value.startswith('mailto://'): + mail_to, email = value.rsplit('://', 1) + self.email_validator(email) + else: + self.url_validator(value) + + class LabPage(BasePage): subpage_types = ['RFPPage'] parent_page_types = ['LabIndex'] @@ -131,7 +146,7 @@ class LabPage(BasePage): on_delete=models.SET_NULL, related_name='lab_public', ) - lab_link = models.URLField(blank=True, verbose_name='External link') + lab_link = models.CharField(blank=True, max_length=255, verbose_name='External link', validators=[MailToAndURLValidator()]) link_text = models.CharField(max_length=255, help_text='Text to display on the button for external links', blank=True) body = StreamField(LabBlock()) diff --git a/opentech/public/funds/templates/public_funds/blocks/related_projects.html b/opentech/public/funds/templates/public_funds/blocks/related_projects.html index 415e2d9b6ad11d59dca8cd0154455c969dad1d63..c3606bd6d83624f1918700d4a288be583bdd6748 100644 --- a/opentech/public/funds/templates/public_funds/blocks/related_projects.html +++ b/opentech/public/funds/templates/public_funds/blocks/related_projects.html @@ -1,9 +1,40 @@ -{% if page.projectfunding_set.all %} +{% if page.projectfunding_set.unique %} <div class="wrapper wrapper--breakout"> <div class="wrapper--media-boxes"> <div class="grid grid--two grid--medium-gap"> - {% for funding in page.projectfunding_set.all %} - {% include "public_funds/includes/project_listing.html" with project=funding.page %} + {% for funding in page.projectfunding_set.unique %} + {% if funding.page.live %} + {% if forloop.counter0 == 10 %} + <input class="show-more--checkbox" type="checkbox" id="projects-toggle"> + <label class="link link--button link--button__center show-more--button" for="projects-toggle">Show more</label> + {% endif %} + {% if forloop.counter0 < 10 %} + {% include "public_funds/includes/project_listing.html" with project=funding.page %} + {% else %} + {% include "public_funds/includes/project_listing.html" with project=funding.page class="show-more--target" %} + {% endif %} + {% endif %} + {% endfor %} + </div> + </div> + </div> +{% endif %} +{% if page.funding_set.unique %} + <div class="wrapper wrapper--breakout"> + <div class="wrapper--media-boxes"> + <div class="grid grid--two grid--medium-gap"> + {% for funding in page.funding_set.unique %} + {% if forloop.counter0 == 10 %} + <input class="show-more--checkbox" type="checkbox" id="fellows-toggle"> + <label class="link link--button link--button__center show-more--button" for="fellows-toggle">Show more</label> + {% endif %} + {% if funding.page.active and funding.page.live %} + {% if forloop.counter0 < 10 %} + {% include "public_funds/includes/reviewer_listing.html" with person=funding.page.specific %} + {% else %} + {% include "public_funds/includes/reviewer_listing.html" with person=funding.page.specific class="show-more--target"%} + {% endif %} + {% endif %} {% endfor %} </div> </div> diff --git a/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html b/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html index 1fb07e0684e8b7254af4ee366b3e1eb872c12397..667d495ec6e5c44e5e6c6e967da69dfc06e898e4 100644 --- a/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html +++ b/opentech/public/funds/templates/public_funds/blocks/related_reviewers.html @@ -5,7 +5,15 @@ {% for person in page.reviewers.all %} {% with person_page=person.reviewer.specific %} {% if person_page.active and person_page.live %} - {% include "public_funds/includes/reviewer_listing.html" with person=person.reviewer.specific %} + {% if forloop.counter0 == 10 %} + <input class="show-more--checkbox" type="checkbox" id="reviewers-toggle"> + <label class="link link--button link--button__center show-more--button" for="reviewers-toggle">Show more</label> + {% endif %} + {% if forloop.counter0 < 10 %} + {% include "public_funds/includes/reviewer_listing.html" with person=person.reviewer.specific %} + {% else %} + {% include "public_funds/includes/reviewer_listing.html" with person=person.reviewer.specific class="show-more--target" %} + {% endif %} {% endif %} {% endwith %} {% endfor %} diff --git a/opentech/public/funds/templates/public_funds/includes/project_listing.html b/opentech/public/funds/templates/public_funds/includes/project_listing.html index a6e573e908e8364a192e1e3a30b6d0885b700127..cdf06d082455691d1258a4a7ffe61fba84f1394d 100644 --- a/opentech/public/funds/templates/public_funds/includes/project_listing.html +++ b/opentech/public/funds/templates/public_funds/includes/project_listing.html @@ -1,5 +1,5 @@ {% load wagtailcore_tags wagtailimages_tags %} -<a class="media-box" href="{% pageurl project %}"> +<a class="media-box {{ class }}" href="{% pageurl project %}"> {% image project.icon max-210x235 as project_icon %} {% include "utils/includes/media_box_icon.html" with page_icon=project_icon listing=True %} @@ -10,4 +10,3 @@ {% endif %} </div> </a> - diff --git a/opentech/public/funds/templates/public_funds/includes/reviewer_listing.html b/opentech/public/funds/templates/public_funds/includes/reviewer_listing.html index 82fdff0357210b2c746833d2846633a194b8497f..1d439aedafe1992f6edf647b0d0e392904bec059 100644 --- a/opentech/public/funds/templates/public_funds/includes/reviewer_listing.html +++ b/opentech/public/funds/templates/public_funds/includes/reviewer_listing.html @@ -1,5 +1,5 @@ {% load wagtailcore_tags wagtailimages_tags %} -<a class="media-box" href="{% pageurl person %}"> +<a class="media-box {{ class }}" href="{% pageurl person %}"> {% image person.photo max-210x235 as person_photo %} {% include "utils/includes/media_box_icon.html" with page_icon=person_photo listing=True %} diff --git a/opentech/public/people/migrations/0012_personindexpage_introduction.py b/opentech/public/people/migrations/0012_personindexpage_introduction.py new file mode 100644 index 0000000000000000000000000000000000000000..1a4b6015c94f20e51df70afbbe8d7c323c033b9e --- /dev/null +++ b/opentech/public/people/migrations/0012_personindexpage_introduction.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.2 on 2018-08-31 19:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('people', '0011_change_the_contact_keys'), + ] + + operations = [ + migrations.AddField( + model_name='personindexpage', + name='introduction', + field=models.TextField(blank=True), + ), + ] diff --git a/opentech/public/people/models.py b/opentech/public/people/models.py index 5bcd05d254c03db5360c9d1d07c7cee79cfad63f..7a85671d438943900446726531baeeedad5559e8 100644 --- a/opentech/public/people/models.py +++ b/opentech/public/people/models.py @@ -73,9 +73,16 @@ class PersonPagePersonType(models.Model): return self.person_type.title +class FundingQueryset(models.QuerySet): + def unique(self): + return self.order_by().distinct('page') + + class Funding(BaseFunding): page = ParentalKey('PersonPage', related_name='funding') + objects = FundingQueryset.as_manager() + class PersonContactInfomation(Orderable): methods = ( @@ -177,6 +184,16 @@ class PersonIndexPage(BasePage): subpage_types = ['PersonPage'] parent_page_types = ['standardpages.IndexPage'] + introduction = models.TextField(blank=True) + + content_panels = BasePage.content_panels + [ + FieldPanel('introduction'), + ] + + search_fields = BasePage.search_fields + [ + index.SearchField('introduction'), + ] + def get_context(self, request, *args, **kwargs): people = PersonPage.objects.live().public().descendant_of(self).order_by( 'title', diff --git a/opentech/public/people/templates/people/includes/person_listing.html b/opentech/public/people/templates/people/includes/person_listing.html index 91986fdaaf67831f844a1efd3b8b58c5b32da227..9a6ce2e7bea505c812151ecf58097cbf3a1488ca 100644 --- a/opentech/public/people/templates/people/includes/person_listing.html +++ b/opentech/public/people/templates/people/includes/person_listing.html @@ -1,8 +1,13 @@ {% load wagtailcore_tags wagtailimages_tags %} -<a class="listing" href="{% pageurl person %}"> - {% if person.photo %} - {% image person.photo fill-180x180 class="listing__image" %} - {% endif %} +<a class="listing {{ class }}" href="{% pageurl person %}"> + <div class="listing__image listing__image--default"> + {% if person.photo %} + {% image person.photo fill-180x180 %} + {% else %} + <svg><use xlink:href="#logo-mobile-no-text"></use></svg> + {% endif %} + + </div> {% for type in person.person_types.all %} <h6 class="listing__category">{{ type }}</h6> {% endfor %} diff --git a/opentech/public/people/templates/people/person_index_page.html b/opentech/public/people/templates/people/person_index_page.html index 9713a67b44a841fdd23de8f7de15096df07f9caa..87101a091222f5e08d28513d7adc762573f6040d 100644 --- a/opentech/public/people/templates/people/person_index_page.html +++ b/opentech/public/people/templates/people/person_index_page.html @@ -3,6 +3,10 @@ {% block body_class %}light-grey-bg{% endblock %} {% block content %} <div class="wrapper wrapper--small wrapper--inner-space-medium"> + {% if page.introduction %} + <h4 class="heading heading--listings-introduction">{{ page.introduction }}</h4> + {% endif %} + <form class="form" method="GET"> <div class="form__group form__group--checkbox"> <div class="form__select form__select--narrow form__select--inline"> diff --git a/opentech/public/projects/models.py b/opentech/public/projects/models.py index eacc416ec54f2c73ccf1303be59ea62a5719a191..d182c5a942add4c283e29c0913384163774afcfc 100644 --- a/opentech/public/projects/models.py +++ b/opentech/public/projects/models.py @@ -84,9 +84,16 @@ class ProjectPageRelatedPage(RelatedPage): ] +class ProjectFundingQueryset(models.QuerySet): + def unique(self): + return self.order_by().distinct('page') + + class ProjectFunding(BaseFunding): page = ParentalKey('ProjectPage', related_name='funding') + objects = ProjectFundingQueryset.as_manager() + class ProjectPage(FundingMixin, BasePage): STATUSES = ( diff --git a/opentech/public/utils/templates/utils/listing_index.html b/opentech/public/utils/templates/utils/listing_index.html index 24113906239ca4a6b578dbf32ea2ab7a3de861f7..afc20088f9408743d4c6761383e701993ef4d5d2 100644 --- a/opentech/public/utils/templates/utils/listing_index.html +++ b/opentech/public/utils/templates/utils/listing_index.html @@ -21,12 +21,18 @@ </div> {% endif %} - {% if subpage.deadline %} <p class="listing__deadline"> - <svg class="icon icon--calendar icon--small"><use xlink:href="#calendar"></use></svg> - <span>Next deadline: {{ subpage.deadline|date:"M j, Y" }}</span> + {% if subpage.is_open %} + {% if subpage.deadline %} + <svg class="icon icon--calendar icon--small"><use xlink:href="#calendar"></use></svg> + <span>Next deadline: {{ subpage.deadline|date:"M j, Y" }}</span> + {% else %} + Open + {% endif %} + {% else %} + Closed + {% endif %} </p> - {% endif %} <h4 class="listing__title">{{ subpage.listing_title|default:subpage.title }}</h4> diff --git a/opentech/static_src/src/sass/public/components/_link.scss b/opentech/static_src/src/sass/public/components/_link.scss index 825ea267041ccc7bcd37576fb65c3cd21fbd78ca..b22db3c619db81d063c13807b65038ce776cbbac 100644 --- a/opentech/static_src/src/sass/public/components/_link.scss +++ b/opentech/static_src/src/sass/public/components/_link.scss @@ -11,6 +11,11 @@ } } + &__center { + display: block; + width: fit-content; + margin: 0 auto; + } } &--button-secondary { diff --git a/opentech/static_src/src/sass/public/components/_listing.scss b/opentech/static_src/src/sass/public/components/_listing.scss index 4a0e6ec55d60236ec4b7c170447d9d1c6847bf63..dd92921702aa40ad4a662663f4eadefd18dd0eaa 100644 --- a/opentech/static_src/src/sass/public/components/_listing.scss +++ b/opentech/static_src/src/sass/public/components/_listing.scss @@ -100,6 +100,11 @@ height: 180px; margin-bottom: 10px; + > img { + min-height: 100%; + width: auto; + } + @include media-query(tablet-portrait) { position: absolute; top: 0; diff --git a/opentech/static_src/src/sass/public/components/_show-more.scss b/opentech/static_src/src/sass/public/components/_show-more.scss new file mode 100644 index 0000000000000000000000000000000000000000..80bb2d4d4bca3a03520cbc2f3c7da593a327a009 --- /dev/null +++ b/opentech/static_src/src/sass/public/components/_show-more.scss @@ -0,0 +1,28 @@ +.show-more { + &--button { + cursor: pointer; + user-select: none; + + @include media-query(tablet-portrait) { + grid-column: 1 / 3; + } + } + + &--target { + display: none; + } + + &--checkbox { + display: none; + + &:checked { + & ~ .show-more--target { + display: flex; + } + & ~ .show-more--button { + display: none; + } + } + } + +} diff --git a/opentech/static_src/src/sass/public/main.scss b/opentech/static_src/src/sass/public/main.scss index 7f09236fa417640878b5a4f94aaac4377369554e..2c66fe8e0d0edb4db394771200788b05ccbac3e3 100755 --- a/opentech/static_src/src/sass/public/main.scss +++ b/opentech/static_src/src/sass/public/main.scss @@ -35,6 +35,7 @@ @import 'components/rich-text'; @import 'components/section'; @import 'components/select2'; +@import 'components/show-more'; @import 'components/wrapper'; // Layout diff --git a/opentech/templates/base.html b/opentech/templates/base.html index 4a30fb9ae4368b2557a4aecea008c551c01c013f..583fc0cec95abaa36a4417f8ce4e217361f37b36 100644 --- a/opentech/templates/base.html +++ b/opentech/templates/base.html @@ -176,7 +176,7 @@ <span>PGP: <a href="https://keybase.io/opentechfund/pgp_keys.asc?fingerprint=67acddcfb909468536ddbc03f7663861965a90d2">67AC DDCF B909 4685 36DD BC03 F766 3861 965A 90D2</a></span> </p> - <p><a class="link link--underlined" href="/tos">Terms of Use</a></p> + <p><a class="link link--underlined" href="about/tos/">Terms of Use</a></p> <p>Test the OTF website for censorship</p> diff --git a/opentech/templates/includes/pagination.html b/opentech/templates/includes/pagination.html index 3fe0bf2820865c9d4bee7072f29c7d0e9d3cd73c..a751c13039dd70bf9b7af55164c62168c6de1ea6 100644 --- a/opentech/templates/includes/pagination.html +++ b/opentech/templates/includes/pagination.html @@ -2,7 +2,7 @@ <nav role="navigation" aria-label="Pagination"> <ul class="pagination"> {% if paginator_page.has_previous %} - <li class="previous"><a href="?page={{ paginator_page.previous_page_number }}{% if search_query %}&query={{ search_query|urlencode }}{% endif %}{% if extra_url_params %}&{{ extra_url_params }}{% endif %}">previous</a></li> + <li class="previous"><a href="?page={{ paginator_page.previous_page_number }}{% for param, value in request.GET.items %}{% if param != "page" %}&{{param}}={{value|urlencode}}{% endif %}{% endfor %}">previous</a></li> {% endif %} <li class="cardinality"> @@ -10,7 +10,7 @@ </li> {% if paginator_page.has_next %} - <li class="next"><a href="?page={{ paginator_page.next_page_number }}{% if search_query %}&query={{ search_query|urlencode }}{% endif %}{% if extra_url_params %}&{{ extra_url_params }}{% endif %}">next</a></li> + <li class="next"><a href="?page={{ paginator_page.next_page_number }}{% for param, value in request.GET.items %}{% if param != "page" %}&{{param}}={{value|urlencode}}{% endif %}{% endfor %}">next</a></li> {% endif %} </ul> </nav>{% endif %}