From 9ee393ca141c07df5ce796c0dbf0f25b4ab201a1 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar <theskumar@users.noreply.github.com> Date: Wed, 10 Jan 2024 13:57:09 +0530 Subject: [PATCH] Remove "people" app - Updates migrations to delete tables - update sandbox-db with removed tables Depends on #3716 --- .../people/management/commands/__init__.py | 0 .../management/commands/migrate_people.py | 317 ------------------ ...0017_remove_fundreviewers_page_and_more.py | 88 +++++ hypha/public/people/models.py | 278 +-------------- .../people/admin/js/update_person_title.js | 25 -- .../people/includes/person_listing.html | 18 - .../templates/people/person_index_page.html | 44 --- .../people/templates/people/person_page.html | 59 ---- hypha/public/people/wagtail_hooks.py | 10 - 9 files changed, 90 insertions(+), 749 deletions(-) delete mode 100644 hypha/public/people/management/commands/__init__.py delete mode 100644 hypha/public/people/management/commands/migrate_people.py create mode 100644 hypha/public/people/migrations/0017_remove_fundreviewers_page_and_more.py delete mode 100644 hypha/public/people/static/people/admin/js/update_person_title.js delete mode 100644 hypha/public/people/templates/people/includes/person_listing.html delete mode 100644 hypha/public/people/templates/people/person_index_page.html delete mode 100644 hypha/public/people/templates/people/person_page.html delete mode 100644 hypha/public/people/wagtail_hooks.py diff --git a/hypha/public/people/management/commands/__init__.py b/hypha/public/people/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/hypha/public/people/management/commands/migrate_people.py b/hypha/public/people/management/commands/migrate_people.py deleted file mode 100644 index 781430151c..0000000000 --- a/hypha/public/people/management/commands/migrate_people.py +++ /dev/null @@ -1,317 +0,0 @@ -import argparse -import itertools -import json -import mimetypes -from datetime import datetime, timezone -from io import BytesIO -from urllib.parse import urlsplit - -import bleach -import requests -from django.core.files.images import ImageFile -from django.core.management.base import BaseCommand -from django.db import transaction -from django.db.utils import IntegrityError -from PIL import Image -from wagtail.admin.rich_text.converters.editor_html import EditorHTMLConverter -from wagtail.images import get_image_model -from wagtail.models import Page -from wagtail.rich_text import RichText - -from hypha.apply.categories.categories_seed import CATEGORIES -from hypha.apply.categories.models import Category, Option -from hypha.public.people.models import ( - Funding, - FundReviewers, - PersonContactInfomation, - PersonIndexPage, - PersonPage, - PersonPagePersonType, - PersonType, - SocialMediaProfile, -) - -WagtailImage = get_image_model() - -VALID_IMAGE_EXTENSIONS = [ - ".jpg", - ".jpeg", - ".png", - ".gif", -] - -VALID_IMAGE_MIMETYPES = ["image"] - - -def valid_url_extension(url, extension_list=VALID_IMAGE_EXTENSIONS): - return any(url.endswith(e) for e in extension_list) - - -def valid_url_mimetype(url, mimetype_list=VALID_IMAGE_MIMETYPES): - mimetype, encoding = mimetypes.guess_type(url) - if mimetype: - return any(mimetype.startswith(m) for m in mimetype_list) - else: - return False - - -class Command(BaseCommand): - help = "Person migration script. Requires a source JSON file." - data = [] - terms = {} - whitelister = EditorHTMLConverter().whitelister - - def add_arguments(self, parser): - parser.add_argument( - "source", type=argparse.FileType("r"), help="Migration source JSON file" - ) - - @transaction.atomic - def handle(self, *args, **options): - # Prepare the list of categories. - for item in CATEGORIES: - category, _ = Category.objects.get_or_create(name=item["category"]) - option, _ = Option.objects.get_or_create( - value=item["name"], category=category - ) - self.terms[item["tid"]] = option - - self.parent_page = PersonIndexPage.objects.first() - - if not self.parent_page: - raise PersonIndexPage.DoesNotExist( - "Project Index Page must exist to import projects" - ) - - self.types = { - "team": PersonType.objects.get_or_create(title="Team")[0], - "council": PersonType.objects.get_or_create(title="Advisory Council")[0], - "fellow": PersonType.objects.get_or_create(title="Fellow")[0], - } - - self.funds = { - "3625": Page.objects.get(title="Internet Freedom Fund"), - "3654": Page.objects.get(title="Rapid Response Fund"), - "3905": Page.objects.get(title="Core Infrastructure Fund"), - "7791": Page.objects.get(title="Community Lab"), - "3618": Page.objects.get(title="Information Controls Fellowship"), - "3613": None, - "3681": Page.objects.get(title="Digital Integrity Fellowship"), - } - - self.review_funds = { - "393": Page.objects.get(title="Internet Freedom Fund"), - "389": Page.objects.get(title="Rapid Response Fund"), - "391": Page.objects.get(title="Core Infrastructure Fund"), - "NOT_USED": Page.objects.get(title="Community Lab"), - "394": Page.objects.get(title="Information Controls Fellowship"), - "390": Page.objects.get(title="Digital Integrity Fellowship"), - } - - with options["source"] as json_data: - self.data = json.load(json_data) - - counter = 0 - for id in self.data: - self.process(id) - counter += 1 - - self.stdout.write(f"Imported {counter} submissions.") - - def process(self, id): - node = self.data[id] - print(node["title"].encode("utf8")) - - try: - person = PersonPage.objects.get(drupal_id=node["nid"]) - except PersonPage.DoesNotExist: - person = PersonPage(drupal_id=node["nid"]) - - # TODO timezone? - person.submit_time = datetime.fromtimestamp(int(node["created"]), timezone.utc) - - *first_name, last_name = node["title"].split() - - person.first_name = " ".join(first_name) - person.last_name = last_name - - person.title = node["title"] - - person.job_title = self.get_field(node, "field_team_title") - - person.active = bool(int(node["field_team_status"]["value"])) - - person.person_types.clear() - for person_type in self.ensure_iterable(node["field_team_type"]): - person.person_types.add( - PersonPagePersonType( - person_type=self.types[person_type["value"]], - ) - ) - - image_url_base = "https://www.opentech.fund/sites/default/files/" - - try: - uri = node["field_team_photo"]["uri"] - except TypeError: - # There was no image - pass - else: - parts = urlsplit(uri) - image_url = image_url_base + parts.netloc + parts.path - person.photo = self.wagtail_image_obj_from_url( - image_url, node["field_team_photo"]["fid"] - ) - - cleaned_body = self.whitelister.clean(self.get_field(node, "body")) - - # Use the first sentence of the body as an intro - very_clean_body = bleach.clean(cleaned_body, strip=True) - very_clean_body = very_clean_body.replace(".\n", ". ") - parts = very_clean_body.split(". ") - introduction = "" - while len(introduction) < 20: - try: - introduction += parts.pop(0) - introduction += ". " - except IndexError: - break - - introduction = introduction.strip() - person.introduction = introduction - body_without_intro = cleaned_body.replace(introduction, "").strip() - person.biography = [("paragraph", RichText(body_without_intro))] - - person.social_media_profile.clear() - - if self.get_field(node, "field_team_twitter"): - person.social_media_profile.add( - SocialMediaProfile( - service="twitter", - username=self.get_field(node, "field_team_twitter"), - ) - ) - - person.contact_details.clear() - for contact in ["im", "otr", "irc", "pgp", "phone"]: - if self.get_field(node, f"field_team_{contact}"): - person.contact_details.add( - PersonContactInfomation( - contact_method=contact, - contact_detail=self.get_field(node, f"field_team_{contact}"), - ) - ) - - person.funds_reviewed.clear() - for reviewer in self.ensure_iterable(node["field_team_review_panel"]): - person.funds_reviewed.add( - FundReviewers( - page=self.review_funds[reviewer["tid"]], - ) - ) - - # Funding - person.funding.clear() - - years = self.ensure_iterable(node["field_project_funding_year"]) - amounts = self.ensure_iterable(node["field_project_funding_amount"]) - durations = self.ensure_iterable(node["field_project_term_time"]) - funds = self.ensure_iterable(node["field_project_funding_request"]) - for year, amount, duration, fund in itertools.zip_longest( - years, amounts, durations, funds - ): - try: - fund = self.funds[fund["target_id"]] - except TypeError: - fund = None - - try: - duration = duration["value"] - except TypeError: - duration = 0 - - try: - amount = amount["value"] - except TypeError: - # This is an error, don't give funding - continue - - person.funding.add( - Funding( - value=amount, - year=year["value"], - duration=duration, - source=fund, - ) - ) - - try: - if not person.get_parent(): - self.parent_page.add_child(instance=person) - person.save_revision().publish() - self.stdout.write( - f"Processed \"{node['title'].encode('utf8')}\" ({node['nid']})" - ) - except IntegrityError: - self.stdout.write( - f"*** Skipped \"{node['title']}\" ({node['nid']}) due to IntegrityError" - ) - pass - - def ensure_iterable(self, value): - if isinstance(value, dict): - value = [value] - return value - - def get_field(self, node, field): - try: - return node[field]["safe_value"] - except TypeError: - pass - try: - return node[field]["value"] - except TypeError: - return "" - - def get_referenced_term(self, tid): - try: - return self.terms[tid] - except KeyError: - return None - - def nl2br(self, value): - return value.replace("\r\n", "<br>\n") - - @staticmethod - def wagtail_image_obj_from_url(url, drupal_id=None): - """ - Get the image from the Nesta site if it doesn't already exist. - """ - - if drupal_id is not None and drupal_id: - try: - return WagtailImage.objects.get(drupal_id=drupal_id) - except WagtailImage.DoesNotExist: - pass - - if url and valid_url_extension(url) and valid_url_mimetype(url): - r = requests.get(url, stream=True) - - if r.status_code == requests.codes.ok: - img_buffer = BytesIO(r.content) - img_filename = url.rsplit("/", 1)[1] - - # Test downloaded file is valid image file - try: - pil_image = Image.open(img_buffer) - pil_image.verify() - except Exception as e: - print(f"Invalid image {url}: {e}") - else: - img = WagtailImage.objects.create( - title=img_filename, - file=ImageFile(img_buffer, name=img_filename), - drupal_id=drupal_id, - ) - return img - return None diff --git a/hypha/public/people/migrations/0017_remove_fundreviewers_page_and_more.py b/hypha/public/people/migrations/0017_remove_fundreviewers_page_and_more.py new file mode 100644 index 0000000000..3a1d985f48 --- /dev/null +++ b/hypha/public/people/migrations/0017_remove_fundreviewers_page_and_more.py @@ -0,0 +1,88 @@ +# Generated by Django 4.2.9 on 2024-01-10 08:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("people", "0016_remove_personindexpage_social_image_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="fundreviewers", + name="page", + ), + migrations.RemoveField( + model_name="fundreviewers", + name="reviewer", + ), + migrations.RemoveField( + model_name="personcontactinfomation", + name="page", + ), + migrations.RemoveField( + model_name="personindexpage", + name="header_image", + ), + migrations.RemoveField( + model_name="personindexpage", + name="listing_image", + ), + migrations.RemoveField( + model_name="personindexpage", + name="page_ptr", + ), + migrations.RemoveField( + model_name="personpage", + name="header_image", + ), + migrations.RemoveField( + model_name="personpage", + name="listing_image", + ), + migrations.RemoveField( + model_name="personpage", + name="page_ptr", + ), + migrations.RemoveField( + model_name="personpage", + name="photo", + ), + migrations.RemoveField( + model_name="personpagepersontype", + name="page", + ), + migrations.RemoveField( + model_name="personpagepersontype", + name="person_type", + ), + migrations.RemoveField( + model_name="socialmediaprofile", + name="person_page", + ), + migrations.DeleteModel( + name="Funding", + ), + migrations.DeleteModel( + name="FundReviewers", + ), + migrations.DeleteModel( + name="PersonContactInfomation", + ), + migrations.DeleteModel( + name="PersonIndexPage", + ), + migrations.DeleteModel( + name="PersonPage", + ), + migrations.DeleteModel( + name="PersonPagePersonType", + ), + migrations.DeleteModel( + name="PersonType", + ), + migrations.DeleteModel( + name="SocialMediaProfile", + ), + ] diff --git a/hypha/public/people/models.py b/hypha/public/people/models.py index 5a800da655..984ab8ff7f 100644 --- a/hypha/public/people/models.py +++ b/hypha/public/people/models.py @@ -1,276 +1,2 @@ -from django.conf import settings -from django.core.exceptions import ValidationError -from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator -from django.db import models -from django.utils.translation import gettext_lazy as _ -from modelcluster.fields import ParentalKey -from pagedown.widgets import PagedownWidget -from wagtail.admin.panels import ( - FieldPanel, - FieldRowPanel, - InlinePanel, - MultiFieldPanel, - PageChooserPanel, -) -from wagtail.fields import StreamField -from wagtail.models import Orderable, PageManager -from wagtail.query import PageQuerySet -from wagtail.search import index - -from hypha.public.utils.blocks import StoryBlock -from hypha.public.utils.models import BaseFunding, BasePage, FundingMixin, RelatedPage - - -class SocialMediaProfile(models.Model): - person_page = ParentalKey("PersonPage", related_name="social_media_profile") - site_titles = ( - ("twitter", "Twitter"), - ("linkedin", "LinkedIn"), - ) - site_urls = ( - ("twitter", "https://twitter.com/"), - ("linkedin", "https://www.linkedin.com/in/"), - ) - service = models.CharField(max_length=200, choices=site_titles) - username = models.CharField(max_length=255) - - @property - def profile_url(self): - return dict(self.site_urls)[self.service] + self.username - - def clean(self): - if self.service == "twitter" and self.username.startswith("@"): - self.username = self.username[1:] - - -class PersonType(models.Model): - title = models.CharField(max_length=255) - - def __str__(self): - return self.title - - -class PersonPagePersonType(models.Model): - page = ParentalKey("PersonPage", related_name="person_types") - person_type = models.ForeignKey( - "PersonType", - related_name="+", - on_delete=models.PROTECT, - ) - - panels = [FieldPanel("person_type")] - - def __str__(self): - return self.person_type.title - - -class FundingQuerySet(models.QuerySet): - def people(self): - return ( - PersonPage.objects.filter(id__in=self.values_list("page__id")) - .live() - .active() - .public() - ) - - -class Funding(BaseFunding): - page = ParentalKey("PersonPage", related_name="funding") - - objects = FundingQuerySet.as_manager() - - -class PersonContactInfomation(Orderable): - methods = ( - ("irc", "IRC"), - ("im", "IM/Jabber/XMPP"), - ("phone", "Phone"), - ("pgp", "PGP fingerprint"), - ("otr", "OTR fingerprint"), - ) - page = ParentalKey("PersonPage", related_name="contact_details") - contact_method = models.CharField(max_length=255, choices=methods, blank=True) - other_method = models.CharField(max_length=255, blank=True, verbose_name=_("Other")) - contact_detail = models.CharField(max_length=255) - - panels = [ - FieldRowPanel( - [ - FieldPanel("contact_method"), - FieldPanel("other_method"), - ] - ), - FieldPanel("contact_detail"), - ] - - @property - def method_display(self): - return self.other_method or self.get_contact_method_display() - - def clean(self): - if not (self.contact_method or self.other_method): - raise ValidationError( - { - "contact_method": "Please select or type at least one contact method.", - "other_method": "", - } - ) - - if self.contact_method and self.other_method: - raise ValidationError( - { - "contact_method": "Please only select or type one contact method.", - "other_method": "", - } - ) - - -class ReviewerQuerySet(models.QuerySet): - def people(self): - return ( - PersonPage.objects.filter(id__in=self.values_list("reviewer__id")) - .live() - .active() - .public() - ) - - -class FundReviewers(RelatedPage): - page = models.ForeignKey( - "wagtailcore.Page", - null=True, - blank=True, - on_delete=models.SET_NULL, - related_name="reviewers", - ) - reviewer = ParentalKey("PersonPage", related_name="funds_reviewed") - - objects = ReviewerQuerySet.as_manager() - - panels = [ - PageChooserPanel("page", "public_funds.FundPage"), - ] - - -class PersonQuerySet(PageQuerySet): - def active(self): - return self.filter(active=True) - - -class PersonPage(FundingMixin, BasePage): - subpage_types = [] - parent_page_types = ["PersonIndexPage"] - - drupal_id = models.IntegerField(null=True, blank=True, editable=False) - - first_name = models.CharField(max_length=255, blank=True) - last_name = models.CharField(max_length=255) - photo = models.ForeignKey( - "images.CustomImage", - null=True, - blank=True, - related_name="+", - on_delete=models.SET_NULL, - ) - active = models.BooleanField(default=True) - job_title = models.CharField(max_length=255, blank=True) - introduction = models.TextField(blank=True) - website = models.URLField(blank=True, max_length=255) - biography = StreamField(StoryBlock(), blank=True, use_json_field=True) - email = models.EmailField(blank=True) - - objects = PageManager.from_queryset(PersonQuerySet)() - - search_fields = BasePage.search_fields + [ - index.SearchField("introduction"), - index.SearchField("biography"), - ] - - content_panels = ( - BasePage.content_panels - + [ - MultiFieldPanel( - [ - FieldPanel("first_name"), - FieldPanel("last_name"), - ], - heading=_("Name"), - ), - FieldPanel("active"), - FieldPanel("photo"), - FieldPanel("job_title"), - InlinePanel("social_media_profile", label=_("Social accounts")), - FieldPanel("website"), - MultiFieldPanel( - [ - FieldPanel("email"), - InlinePanel("contact_details", label=_("Other Contact Methods")), - ], - heading=_("Contact information"), - ), - InlinePanel("person_types", label=_("Person types")), - FieldPanel("introduction"), - FieldPanel("biography"), - InlinePanel("funds_reviewed", label=_("Funds Reviewed")), - ] - + FundingMixin.content_panels - ) - - -class PersonIndexPage(BasePage): - subpage_types = ["PersonPage"] - parent_page_types = ["standardpages.IndexPage"] - - introduction = models.TextField(blank=True) - - content_panels = BasePage.content_panels + [ - FieldPanel("introduction", widget=PagedownWidget()), - ] - - 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", - ) - .select_related( - "photo", - ) - .prefetch_related( - "person_types__person_type", - ) - ) - - if request.GET.get("person_type") and request.GET.get("person_type").isdigit(): - people = people.filter( - person_types__person_type=request.GET.get("person_type") - ) - - if not request.GET.get("include_inactive") == "true": - people = people.filter(active=True) - - page_number = request.GET.get("page") - paginator = Paginator(people, settings.DEFAULT_PER_PAGE) - try: - people = paginator.page(page_number) - except PageNotAnInteger: - people = paginator.page(1) - except EmptyPage: - people = paginator.page(paginator.num_pages) - - context = super().get_context(request, *args, **kwargs) - context.update( - people=people, - # Only show person types that have been used - person_types=PersonPagePersonType.objects.all() - .values_list("person_type__pk", "person_type__title") - .distinct(), - ) - - return context +# @TODO: This file kept to generate delete migrations, this file should be removed, while removing the app from +# INSTALLED_APPS and removing the migrations folder. diff --git a/hypha/public/people/static/people/admin/js/update_person_title.js b/hypha/public/people/static/people/admin/js/update_person_title.js deleted file mode 100644 index c956d262c6..0000000000 --- a/hypha/public/people/static/people/admin/js/update_person_title.js +++ /dev/null @@ -1,25 +0,0 @@ -$(document).ready(function () { - var $lastNameInput = $("#id_last_name"); - var $firstNameInput = $("#id_first_name"); - var $titleInput = $("#id_title"); - var $slugInput = $("#id_slug"); - - $firstNameInput.on("input", function () { - joinFirstNameLastName(); - }); - - $lastNameInput.on("input", function () { - joinFirstNameLastName(); - }); - - function joinFirstNameLastName() { - var firstName = $firstNameInput.val(); - var lastName = $lastNameInput.val(); - var title = firstName + " " + lastName; - - $slugInput.data("previous-val", $slugInput.val()); - $titleInput.data("previous-val", $titleInput.val()); - $titleInput.val(title); - $titleInput.blur(); // Trigger slug update - } -}); diff --git a/hypha/public/people/templates/people/includes/person_listing.html b/hypha/public/people/templates/people/includes/person_listing.html deleted file mode 100644 index 9a6ce2e7be..0000000000 --- a/hypha/public/people/templates/people/includes/person_listing.html +++ /dev/null @@ -1,18 +0,0 @@ -{% load wagtailcore_tags wagtailimages_tags %} -<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 %} - <h4 class="listing__title">{{ person.first_name }} {{ person.last_name }}</h4> - {% if person.listing_summary or person.introduction %} - <h6 class="listing__teaser">{{ person.listing_summary|default:person.introduction|truncatechars:235 }}</h6> - {% endif %} -</a> diff --git a/hypha/public/people/templates/people/person_index_page.html b/hypha/public/people/templates/people/person_index_page.html deleted file mode 100644 index b4ce4bd591..0000000000 --- a/hypha/public/people/templates/people/person_index_page.html +++ /dev/null @@ -1,44 +0,0 @@ -{% extends "base.html" %} -{% load wagtailcore_tags markdown_tags bleach_tags %} -{% 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|markdown|bleach }}</h4> - {% endif %} - - <form class="form" method="GET"> - <div class="form__group form__group--checkbox"> - <div class="form__select form__select--narrow form__select--inline"> - <select name="person_type"> - <option value="">All</option> - {% for person_type in person_types %} - <option value="{{ person_type.0 }}" {% if request.GET.person_type == person_type.0|slugify %}selected="selected"{% endif %}>{{ person_type.1 }}</option> - {% endfor %} - </select> - </div> - </div> - <div class="form__group form__group--checkbox"> - <label for="inactive" class="form__question form__question--boolean_field checkbox_input">Include Inactive</label> - <div class="form__item"> - <input type="checkbox" id="inactive" name="include_inactive" value="true" {% if request.GET.include_inactive %} checked {% endif %}> - <label for="inactive"></label> - </div> - </div> - <button class="link link--button link--button__stretch" type="submit">Filter</button> - </form> - - <div class="wrapper wrapper--listings"> - {% if people.paginator.count %} - {% for person in people %} - {% include "people/includes/person_listing.html" with person=person %} - {% endfor %} - - {% include "includes/pagination.html" with paginator_page=people %} - {% else %} - {# no results #} - {% endif %} - </div> - </div> - -{% endblock %} diff --git a/hypha/public/people/templates/people/person_page.html b/hypha/public/people/templates/people/person_page.html deleted file mode 100644 index 02fe3ce112..0000000000 --- a/hypha/public/people/templates/people/person_page.html +++ /dev/null @@ -1,59 +0,0 @@ -{% extends "base.html" %} - -{% load wagtailcore_tags wagtailimages_tags %} - -{% block content %} - <section class="wrapper wrapper--small wrapper--inner-space-large wrapper--sidebar"> - <div class="wrapper--sidebar--inner"> - {% for person_type in page.person_types.all %} - <h5 class="heading heading--no-margin">{{ person_type }}</h5> - {% endfor %} - - {% if page.job_title %} - <h4 class="heading">{{ page.job_title }}</h4> - {% endif %} - - {% if page.photo %} - {% image page.photo fill-210x235 class="image image--headshot-mobile" %} - {% endif %} - - {% if page.introduction %} - <h4 class="heading heading--person-introduction">{{ page.introduction }}</h4> - {% endif %} - - {% include_block page.biography %} - - {% if page.website %} - <p class="list list--contact"><span>Website:</span> <a href="{{ page.website }}">{{ page.website }}</a></p> - {% endif %} - - {% if page.email %} - <p class="list list--contact"><span>Email:</span> <a href="{{ page.email }}">{{ page.email }}</a></p> - {% endif %} - - {% with contact_details=page.contact_details.all %} - {% if contact_details %} - {% for contact in contact_details %} - <p class="list list--contact"><span>{{ contact.method_display }}:</span> {{ contact.contact_detail }}</p> - {% endfor %} - {% endif %} - {% endwith %} - {% include "utils/includes/funding.html" with class="wrapper--top-outer-space-small" %} - </div> - - <div> - {% if page.photo %} - {% image page.photo fill-210x235 class="image image--headshot-desktop" %} - {% endif %} - - {% if page.social_media_profile.all %} - <h5>Follow {{ page.first_name }}</h5> - {% for item in page.social_media_profile.all %} - <a aria-label="Social media link" href="{{ item.profile_url }}"> - <svg class="icon icon--social-share icon--{{item.service}}-share"><use xlink:href="#{{item.service}}"></use></svg> - </a> - {% endfor %} - {% endif %} - </div> - </section> -{% endblock %} diff --git a/hypha/public/people/wagtail_hooks.py b/hypha/public/people/wagtail_hooks.py deleted file mode 100644 index 2726ec34dd..0000000000 --- a/hypha/public/people/wagtail_hooks.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.templatetags.static import static -from django.utils.safestring import mark_safe -from wagtail import hooks - - -@hooks.register("insert_editor_js") -def editor_js(): - return mark_safe( - '<script src="%s"></script>' % static("people/admin/js/update_person_title.js") - )