Libraries BaseLibraryPage (#10765)
* Libraries profile detail page * Define detail cards for RCC and RH * Add Library base detail page * Add abstract Library detail page * Remove `rcc` and `research` prefixes from models * Fix image height and width attributes * Abstract detail page factory * Lint * Better error messages * Fix mistyped factory model * Add docstrings * Rename JS file * Rename libraries filter_form * Base libraries LibraryPage * Change years to year on filter form * Add an abstract BaseLibraryPage * Add libraries level `constants` module * Improve API * Fix tests * Lint * Fix type annotation imports * Remove duplicated block
This commit is contained in:
Родитель
3a06b2b756
Коммит
529c1a3092
|
@ -52,8 +52,8 @@ const sources = {
|
|||
source: `buyers-guide/editorial-content-index.js`,
|
||||
bundle: true,
|
||||
},
|
||||
"research-hub-library": {
|
||||
source: `foundation/pages/research-hub-library.js`,
|
||||
"libraries-library-page": {
|
||||
source: `foundation/pages/libraries-library-page.js`,
|
||||
bundle: true,
|
||||
},
|
||||
polyfills: {
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
{% extends "pages/libraries/base.html" %}
|
||||
{% load i18n static wagtailcore_tags wagtailimages_tags %}
|
||||
{% block library_content %}
|
||||
<div>
|
||||
{% block breadcrumbs %}{% endblock breadcrumbs %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
</div>
|
||||
<div class="large:tw-w-160 large:tw-h-64 tw-mt-12 tw-mb-8 large:tw-mb-0 large:-tw-ml-12 large:tw-p-12 large:tw-bg-gray-05">
|
||||
{# SEARCH BAR #}
|
||||
{% comment %}
|
||||
The page url is necessary in the form to that the filter anchor link is not carried forward.
|
||||
Say on mobile the user used the "Filter" anchor link to get to the filter section,
|
||||
that adds the `#filter` part to the URL. Submitting the form in that stage without the
|
||||
explicit URL would carry the anchor link forward. That would mean the view is scrolled to the
|
||||
filter section again upon page reload. This seems undesireable.
|
||||
{% endcomment %}
|
||||
<form action="{% pageurl page %}" method="get" accept-charset="utf-8" id="search-form">
|
||||
{% block search_bar %}{% endblock search_bar %}
|
||||
</form>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col large:tw-flex-row-reverse large:tw-gap-16">
|
||||
{# FILTER, SORT AND RESULTS #}
|
||||
{# For side-by-side layout, we need to pull the results up to that the upper end lines up with the search bar. #}
|
||||
<div class="tw-min-w-0 tw-grow large:-tw-mt-64 tw-pb-24">
|
||||
{# SORT AND RESULTS #}
|
||||
<div class="tw-flex tw-flex-col large:tw-flex-row-reverse large:tw-justify-between tw-gap-12">
|
||||
<div class="tw-flex tw-flex-row tw-gap-6">
|
||||
{# FILTER BUTTON #}
|
||||
<div class="large:tw-hidden tw-basis-1/2">
|
||||
{% include "fragments/libraries/filter_button.html" with button=False %}
|
||||
{% include "fragments/libraries/filter_button.html" with button=True %}
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-row tw-items-baseline tw-basis-1/2 large:tw-basis-full">
|
||||
{# SORT SELECT #}
|
||||
<select id="sort-select"
|
||||
name="sort"
|
||||
class="tw-form-control tw-border-gray-40"
|
||||
form="search-form">
|
||||
{% for choice in page.SORT_CHOICES.values %}
|
||||
<option value="{{ choice.value }}" {% if choice == sort %}selected{% endif %}>
|
||||
{{ choice.label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<noscript>
|
||||
{# The sort button is only needed for the no JS case. With JS, the form can be submitted on change of the select #}
|
||||
<button type="submit" class="tw-btn-primary tw-text-base" form="search-form">
|
||||
{% translate "Sort" context "Button" %}
|
||||
</button>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-h4-heading tw-mb-0">
|
||||
{# RESULTS COUNT #}
|
||||
{% if search_query %}
|
||||
{% blocktranslate count counter=detail_pages_count trimmed %}
|
||||
<strong>{{ detail_pages_count }}</strong> result for <q>{{ search_query }}</q>
|
||||
{% plural %}
|
||||
<strong>{{ detail_pages_count }}</strong> results for <q>{{ search_query }}</q>
|
||||
{% endblocktranslate %}
|
||||
{% else %}
|
||||
{% blocktranslate count counter=detail_pages_count trimmed %}
|
||||
<strong>{{ detail_pages_count }}</strong> result
|
||||
{% plural %}
|
||||
<strong>{{ detail_pages_count }}</strong> results
|
||||
{% endblocktranslate %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="tw-list-none tw-mt-16 large:tw-mt-12 tw-mb-12 tw-px-0 tw-border-t tw-border-b tw-border-gray-20 tw-divide-y tw-divide-gray-05">
|
||||
{# RESULTS LIST #}
|
||||
{% block detail_pages %}
|
||||
{% endblock detail_pages %}
|
||||
</ul>
|
||||
<div>
|
||||
{# PAGINATION #}
|
||||
{% include "fragments/pagination.html" with page=detail_pages %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="filter"
|
||||
class=" tw-bg-gray-05 large:tw-block large:tw-mr-0 large:-tw-ml-12 large:tw-overflow-y-clip tw-pt-8 large:tw-pt-0 tw-px-8 small:tw-px-12 medium:tw-px-16 large:tw-px-12 tw-shrink-0 large:tw-w-160 ">
|
||||
{# FILTER SECTION #}
|
||||
<div class="tw-flex tw-justify-end">
|
||||
<button id="filter-section-hide-button"
|
||||
class="tw-hidden large:tw-hidden tw-h-24 tw-w-24 -tw-mt-4 -tw-mr-4 -tw-mb-8 tw-text-3xl tw-font-normal tw-text-blue-80 hover:tw-text-blue-20 tw-bg-transparent"
|
||||
aria-label="{% translate "Close" %}"
|
||||
tabIndex="0">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<h2 class="large:tw-hidden tw-h1-heading">{% translate "Filter" %}</h2>
|
||||
<form action="{% pageurl page %}"
|
||||
method="get"
|
||||
accept-charset="utf-8"
|
||||
id="filter-form">
|
||||
{% include "fragments/libraries/filter_form.html" with form=form %}
|
||||
<div class=" tw-bg-gray-05 tw-bottom-0 -tw-mx-8 small:-tw-mx-12 medium:-tw-mx-16 large:-tw-mx-12 tw-pb-16 large:tw-pb-12 tw-px-8 small:tw-px-12 medium:tw-px-16 large:tw-px-12 tw-sticky ">
|
||||
<div class="tw-pt-12 large:tw-pt-8 tw-border-t tw-border-t-gray-20">
|
||||
<button type="submit" class="tw-w-full tw-btn-primary" form="filter-form">
|
||||
{% translate "Apply filters" context "Button" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock library_content %}
|
||||
{% block extra_scripts %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript" src="{% static "_js/libraries-library-page.compiled.js" %}" async defer></script>
|
||||
{% endblock extra_scripts %}
|
|
@ -1,117 +1,18 @@
|
|||
{% extends "pages/libraries/base.html" %}
|
||||
{% load i18n static wagtailcore_tags wagtailimages_tags breadcrumbs %}
|
||||
{% block library_content %}
|
||||
<div>
|
||||
{% rcc_breadcrumbs %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
</div>
|
||||
<div class="large:tw-w-160 large:tw-h-64 tw-mt-12 tw-mb-8 large:tw-mb-0 large:-tw-ml-12 large:tw-p-12 large:tw-bg-gray-05">
|
||||
{# SEARCH BAR #}
|
||||
{% comment %}
|
||||
The page url is necessary in the form to that the filter anchor link is not carried forward.
|
||||
Say on mobile the user used the "Filter" anchor link to get to the filter section,
|
||||
that adds the `#filter` part to the URL. Submitting the form in that stage without the
|
||||
explicit URL would carry the anchor link forward. That would mean the view is scrolled to the
|
||||
filter section again upon page reload. This seems undesireable.
|
||||
{% endcomment %}
|
||||
<form action="{% pageurl page %}"
|
||||
method="get"
|
||||
accept-charset="utf-8"
|
||||
id="search-form">
|
||||
{% include "fragments/libraries/rcc/search_bar.html" %}
|
||||
</form>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col large:tw-flex-row-reverse large:tw-gap-16">
|
||||
{# FILTER, SORT AND RESULTS #}
|
||||
{# For side-by-side layout, we need to pull the results up to that the upper end lines up with the search bar. #}
|
||||
<div class="tw-min-w-0 tw-grow large:-tw-mt-64 tw-pb-24">
|
||||
{# SORT AND RESULTS #}
|
||||
<div class="tw-flex tw-flex-col large:tw-flex-row-reverse large:tw-justify-between tw-gap-12">
|
||||
<div class="tw-flex tw-flex-row tw-gap-6">
|
||||
{# FILTER BUTTON #}
|
||||
<div class="large:tw-hidden tw-basis-1/2">
|
||||
{% include "fragments/libraries/filter_button.html" with button=False %}
|
||||
{% include "fragments/libraries/filter_button.html" with button=True %}
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-row tw-items-baseline tw-basis-1/2 large:tw-basis-full">
|
||||
{# SORT SELECT #}
|
||||
<select id="sort-select"
|
||||
name="sort"
|
||||
class="tw-form-control tw-border-gray-40"
|
||||
form="search-form">
|
||||
{% for choice in page.SORT_CHOICES.values %}
|
||||
<option value="{{ choice.value }}" {% if choice == sort %}selected{% endif %}>
|
||||
{{ choice.label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<noscript>
|
||||
{# The sort button is only needed for the no JS case. With JS, the form can be submitted on change of the select #}
|
||||
<button type="submit" class="tw-btn-primary tw-text-base" form="search-form">
|
||||
{% translate "Sort" context "Button" %}
|
||||
</button>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-h4-heading tw-mb-0">
|
||||
{# RESULTS COUNT #}
|
||||
{% if search_query %}
|
||||
{% blocktranslate count counter=rcc_detail_pages_count trimmed %}
|
||||
<strong>{{ rcc_detail_pages_count }}</strong> result for <q>{{ search_query }}</q>
|
||||
{% plural %}
|
||||
<strong>{{ rcc_detail_pages_count }}</strong> results for <q>{{ search_query }}</q>
|
||||
{% endblocktranslate %}
|
||||
{% else %}
|
||||
{% blocktranslate count counter=rcc_detail_pages_count trimmed %}
|
||||
<strong>{{ rcc_detail_pages_count }}</strong> result
|
||||
{% plural %}
|
||||
<strong>{{ rcc_detail_pages_count }}</strong> results
|
||||
{% endblocktranslate %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="tw-list-none tw-mt-16 large:tw-mt-12 tw-mb-12 tw-px-0 tw-border-t tw-border-b tw-border-gray-20 tw-divide-y tw-divide-gray-05">
|
||||
{# RESULTS LIST #}
|
||||
{% for rcc_detail_page in rcc_detail_pages %}
|
||||
<li class="tw-m-0 tw-pt-12 tw-pb-12">
|
||||
{% include "fragments/libraries/rcc/detail_card.html" with rcc_detail_page=rcc_detail_page hide_authors=False hide_image_on_mobile=True hide_related_content_types_on_mobile=True %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div>
|
||||
{# PAGINATION #}
|
||||
{% include "fragments/pagination.html" with page=rcc_detail_pages %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="filter"
|
||||
class=" tw-bg-gray-05 large:tw-block large:tw-mr-0 large:-tw-ml-12 large:tw-overflow-y-clip tw-pt-8 large:tw-pt-0 tw-px-8 small:tw-px-12 medium:tw-px-16 large:tw-px-12 tw-shrink-0 large:tw-w-160 ">
|
||||
{# FILTER SECTION #}
|
||||
<div class="tw-flex tw-justify-end">
|
||||
<button id="filter-section-hide-button"
|
||||
class="tw-hidden large:tw-hidden tw-h-24 tw-w-24 -tw-mt-4 -tw-mr-4 -tw-mb-8 tw-text-3xl tw-font-normal tw-text-blue-80 hover:tw-text-blue-20 tw-bg-transparent"
|
||||
aria-label="{% translate "Close" %}"
|
||||
tabIndex="0">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<h2 class="large:tw-hidden tw-h1-heading">{% translate "Filter" %}</h2>
|
||||
<form action="{% pageurl page %}"
|
||||
method="get"
|
||||
accept-charset="utf-8"
|
||||
id="filter-form">
|
||||
{% include "fragments/research_library_form.html" with form=form %}
|
||||
<div class=" tw-bg-gray-05 tw-bottom-0 -tw-mx-8 small:-tw-mx-12 medium:-tw-mx-16 large:-tw-mx-12 tw-pb-16 large:tw-pb-12 tw-px-8 small:tw-px-12 medium:tw-px-16 large:tw-px-12 tw-sticky ">
|
||||
<div class="tw-pt-12 large:tw-pt-8 tw-border-t tw-border-t-gray-20">
|
||||
<button type="submit" class="tw-w-full tw-btn-primary" form="filter-form">
|
||||
{% translate "Apply filters" context "Button" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock library_content %}
|
||||
{% block extra_scripts %}
|
||||
{{ block.super }}
|
||||
<script src="{% static "_js/research-hub-library.compiled.js" %}" async defer></script>
|
||||
{% endblock extra_scripts %}
|
||||
{% extends "pages/libraries/library_page.html" %}
|
||||
{% load static breadcrumbs %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{% rcc_breadcrumbs %}
|
||||
{% endblock breadcrumbs %}
|
||||
|
||||
{% block search_bar %}
|
||||
{% include "fragments/libraries/rcc/search_bar.html" %}
|
||||
{% endblock search_bar %}
|
||||
|
||||
{% block detail_pages %}
|
||||
{% for detail_page in detail_pages %}
|
||||
<li class="tw-m-0 tw-pt-12 tw-pb-12">
|
||||
{% include "fragments/libraries/rcc/detail_card.html" with rcc_detail_page=detail_page hide_authors=False hide_image_on_mobile=True hide_related_content_types_on_mobile=True %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endblock detail_pages %}
|
||||
|
|
|
@ -1,117 +1,18 @@
|
|||
{% extends "pages/libraries/base.html" %}
|
||||
{% load i18n static wagtailcore_tags wagtailimages_tags breadcrumbs %}
|
||||
{% block library_content %}
|
||||
<div>
|
||||
{% research_breadcrumbs %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
</div>
|
||||
<div class="large:tw-w-160 large:tw-h-64 tw-mt-12 tw-mb-8 large:tw-mb-0 large:-tw-ml-12 large:tw-p-12 large:tw-bg-gray-05">
|
||||
{# SEARCH BAR #}
|
||||
{% comment %}
|
||||
The page url is necessary in the form to that the filter anchor link is not carried forward.
|
||||
Say on mobile the user used the "Filter" anchor link to get to the filter section,
|
||||
that adds the `#filter` part to the URL. Submitting the form in that stage without the
|
||||
explicit URL would carry the anchor link forward. That would mean the view is scrolled to the
|
||||
filter section again upon page reload. This seems undesireable.
|
||||
{% endcomment %}
|
||||
<form action="{% pageurl page %}"
|
||||
method="get"
|
||||
accept-charset="utf-8"
|
||||
id="search-form">
|
||||
{% include "fragments/libraries/research_hub/search_bar.html" %}
|
||||
</form>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col large:tw-flex-row-reverse large:tw-gap-16">
|
||||
{# FILTER, SORT AND RESULTS #}
|
||||
{# For side-by-side layout, we need to pull the results up to that the upper end lines up with the search bar. #}
|
||||
<div class="tw-min-w-0 tw-grow large:-tw-mt-64 tw-pb-24">
|
||||
{# SORT AND RESULTS #}
|
||||
<div class="tw-flex tw-flex-col large:tw-flex-row-reverse large:tw-justify-between tw-gap-12">
|
||||
<div class="tw-flex tw-flex-row tw-gap-6">
|
||||
{# FILTER BUTTON #}
|
||||
<div class="large:tw-hidden tw-basis-1/2">
|
||||
{% include "fragments/libraries/filter_button.html" with button=False %}
|
||||
{% include "fragments/libraries/filter_button.html" with button=True %}
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-row tw-items-baseline tw-basis-1/2 large:tw-basis-full">
|
||||
{# SORT SELECT #}
|
||||
<select id='sort-select'
|
||||
name="sort"
|
||||
class="tw-form-control tw-border-gray-40"
|
||||
form="search-form">
|
||||
{% for choice in page.SORT_CHOICES.values %}
|
||||
<option value="{{ choice.value }}" {% if choice == sort %}selected{% endif %}>
|
||||
{{ choice.label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<noscript>
|
||||
{# The sort button is only needed for the no JS case. With JS, the form can be submitted on change of the select #}
|
||||
<button type="submit" class="tw-btn-primary tw-text-base" form="search-form">
|
||||
{% translate 'Sort' context 'Button' %}
|
||||
</button>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-h4-heading tw-mb-0">
|
||||
{# RESULTS COUNT #}
|
||||
{% if search_query %}
|
||||
{% blocktranslate count counter=research_detail_pages_count trimmed %}
|
||||
<strong>{{ research_detail_pages_count }}</strong> result for <q>{{ search_query }}</q>
|
||||
{% plural %}
|
||||
<strong>{{ research_detail_pages_count }}</strong> results for <q>{{ search_query }}</q>
|
||||
{% endblocktranslate %}
|
||||
{% else %}
|
||||
{% blocktranslate count counter=research_detail_pages_count trimmed %}
|
||||
<strong>{{ research_detail_pages_count }}</strong> result
|
||||
{% plural %}
|
||||
<strong>{{ research_detail_pages_count }}</strong> results
|
||||
{% endblocktranslate %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="tw-list-none tw-mt-16 large:tw-mt-12 tw-mb-12 tw-px-0 tw-border-t tw-border-b tw-border-gray-20 tw-divide-y tw-divide-gray-05">
|
||||
{# RESULTS LIST #}
|
||||
{% for research_detail_page in research_detail_pages %}
|
||||
<li class="tw-m-0 tw-pt-12 tw-pb-12">
|
||||
{% include "fragments/libraries/research_hub/detail_card.html" with research_detail_page=research_detail_page hide_image_on_mobile=True hide_related_topics_on_mobile=True %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div>
|
||||
{# PAGINATION #}
|
||||
{% include "fragments/pagination.html" with page=research_detail_pages %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="filter"
|
||||
class=" tw-bg-gray-05 large:tw-block large:tw-mr-0 large:-tw-ml-12 large:tw-overflow-y-clip tw-pt-8 large:tw-pt-0 tw-px-8 small:tw-px-12 medium:tw-px-16 large:tw-px-12 tw-shrink-0 large:tw-w-160 ">
|
||||
{# FILTER SECTION #}
|
||||
<div class="tw-flex tw-justify-end">
|
||||
<button id="filter-section-hide-button"
|
||||
class="tw-hidden large:tw-hidden tw-h-24 tw-w-24 -tw-mt-4 -tw-mr-4 -tw-mb-8 tw-text-3xl tw-font-normal tw-text-blue-80 hover:tw-text-blue-20 tw-bg-transparent"
|
||||
aria-label="{% translate "Close" %}"
|
||||
tabIndex="0">
|
||||
<span aria-hidden="true" class="">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<h2 class="large:tw-hidden tw-h1-heading">{% translate 'Filter' %}</h2>
|
||||
<form action="{% pageurl page %}"
|
||||
method="get"
|
||||
accept-charset="utf-8"
|
||||
id="filter-form">
|
||||
{% include "fragments/research_library_form.html" with form=form %}
|
||||
<div class=" tw-bg-gray-05 tw-bottom-0 -tw-mx-8 small:-tw-mx-12 medium:-tw-mx-16 large:-tw-mx-12 tw-pb-16 large:tw-pb-12 tw-px-8 small:tw-px-12 medium:tw-px-16 large:tw-px-12 tw-sticky ">
|
||||
<div class="tw-pt-12 large:tw-pt-8 tw-border-t tw-border-t-gray-20">
|
||||
<button type="submit" class="tw-w-full tw-btn-primary" form="filter-form">
|
||||
{% translate 'Apply filters' context 'Button' %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock library_content %}
|
||||
{% block extra_scripts %}
|
||||
{{ block.super }}
|
||||
<script src="{% static "_js/research-hub-library.compiled.js" %}" async defer></script>
|
||||
{% endblock extra_scripts %}
|
||||
{% extends "pages/libraries/library_page.html" %}
|
||||
{% load static breadcrumbs %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{% research_breadcrumbs %}
|
||||
{% endblock breadcrumbs %}
|
||||
|
||||
{% block search_bar %}
|
||||
{% include "fragments/libraries/research_hub/search_bar.html" %}
|
||||
{% endblock search_bar %}
|
||||
|
||||
{% block detail_pages %}
|
||||
{% for detail_page in detail_pages %}
|
||||
<li class="tw-m-0 tw-pt-12 tw-pb-12">
|
||||
{% include "fragments/libraries/rcc/detail_card.html" with rcc_detail_page=detail_page hide_authors=False hide_image_on_mobile=True hide_related_content_types_on_mobile=True %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endblock detail_pages %}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
import typing
|
||||
from functools import cached_property
|
||||
from typing import Optional
|
||||
|
||||
from django.core import paginator
|
||||
from django.db import models
|
||||
from wagtail import images as wagtail_images
|
||||
from wagtail.admin import panels
|
||||
from wagtail.images import edit_handlers as image_panels
|
||||
from wagtail_localize.fields import SynchronizedField, TranslatableField
|
||||
|
||||
from networkapi.wagtailpages.pagemodels.base import BasePage
|
||||
from networkapi.wagtailpages.pagemodels.libraries import constants
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from django import forms, http
|
||||
from django import template as django_template
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
|
||||
class BaseLibraryPage(BasePage):
|
||||
"""An abstract template for a library page.
|
||||
|
||||
To define a concrete library page, subclass it and implement the following attributes:
|
||||
- `parent_page_types`: Return the parent page types for this page.
|
||||
- `subpage_types`: Return the subpage types for this page.
|
||||
- `template`: Return the template to use for this page.
|
||||
|
||||
In addition, the following methods have to be implemented:
|
||||
- `get_form`: Return the form class used to filter detail pages.
|
||||
- `get_filtered_detail_pages`: Return the article detail pages that match the given filters in the form.
|
||||
|
||||
Concrete implementation examples can be found in the RCC and Research_Hub apps.
|
||||
"""
|
||||
|
||||
max_count = 1
|
||||
|
||||
template = "pages/libraries/library_page.html"
|
||||
|
||||
SORT_CHOICES = constants.SORT_CHOICES
|
||||
|
||||
banner_image = models.ForeignKey(
|
||||
wagtail_images.get_image_model_string(),
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
|
||||
results_count = models.PositiveSmallIntegerField(
|
||||
default=10,
|
||||
help_text="Maximum number of results to be displayed per page.",
|
||||
)
|
||||
|
||||
content_panels = BasePage.content_panels + [
|
||||
image_panels.FieldPanel("banner_image"),
|
||||
]
|
||||
|
||||
settings_panels = BasePage.settings_panels + [panels.FieldPanel("results_count")]
|
||||
|
||||
translatable_fields = [
|
||||
# Content tab fields
|
||||
TranslatableField("title"),
|
||||
# Promote tab fields
|
||||
SynchronizedField("slug"),
|
||||
TranslatableField("seo_title"),
|
||||
SynchronizedField("show_in_menus"),
|
||||
TranslatableField("search_description"),
|
||||
SynchronizedField("search_image"),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@property
|
||||
def filter_form(self):
|
||||
"""Form class used to filter detail pages for this page."""
|
||||
raise NotImplementedError("Please implement this property in your subclass.")
|
||||
|
||||
@cached_property
|
||||
def detail_pages(self):
|
||||
"""Return the article detail pages that are children of this page."""
|
||||
raise NotImplementedError("Please implement this property in your subclass.")
|
||||
|
||||
@staticmethod
|
||||
def filter_detail_pages(pages: "QuerySet", filter_form: "forms.Form") -> "QuerySet":
|
||||
"""Return the article detail pages that match the given filters in the `filter_form`."""
|
||||
raise NotImplementedError("Please implement this method in your subclass.")
|
||||
|
||||
def get_sorted_filtered_detail_pages(
|
||||
self,
|
||||
*,
|
||||
filter_form: Optional["forms.Form"] = None,
|
||||
sort: constants.SortOption = constants.SORT_NEWEST_FIRST,
|
||||
search_query: Optional[str] = None,
|
||||
) -> "QuerySet":
|
||||
"""Get sorted article detail pages filtered by the form options and search parameters."""
|
||||
detail_pages = self.detail_pages
|
||||
|
||||
if filter_form:
|
||||
detail_pages = self.filter_detail_pages(detail_pages, filter_form)
|
||||
|
||||
detail_pages = detail_pages.order_by(sort.order_by_value)
|
||||
|
||||
if search_query:
|
||||
detail_pages = detail_pages.search(
|
||||
search_query,
|
||||
order_by_relevance=False, # To preserve original ordering
|
||||
)
|
||||
|
||||
return detail_pages
|
||||
|
||||
def get_context(self, request: "http.HttpRequest") -> "django_template.Context":
|
||||
search_query: str = request.GET.get("search", "")
|
||||
sort_value: str = request.GET.get("sort", "")
|
||||
sort: constants.SortOption = constants.SORT_CHOICES.get(sort_value, constants.SORT_NEWEST_FIRST)
|
||||
|
||||
Form = self.filter_form
|
||||
filter_form = Form(request.GET, label_suffix="")
|
||||
|
||||
sorted_and_searched_and_filtered_detail_pages = self.get_sorted_filtered_detail_pages(
|
||||
filter_form=filter_form, search_query=search_query, sort=sort
|
||||
)
|
||||
|
||||
detail_pages_paginator = paginator.Paginator(
|
||||
object_list=sorted_and_searched_and_filtered_detail_pages,
|
||||
per_page=self.results_count,
|
||||
allow_empty_first_page=True,
|
||||
)
|
||||
|
||||
page: Optional[str] = request.GET.get("page")
|
||||
detail_pages_page = detail_pages_paginator.get_page(page)
|
||||
|
||||
context: "django_template.Context" = super().get_context(request)
|
||||
context["search_query"] = search_query
|
||||
context["sort"] = sort
|
||||
context["form"] = filter_form
|
||||
context["detail_pages_count"] = detail_pages_paginator.count
|
||||
context["detail_pages"] = detail_pages_page
|
||||
return context
|
||||
|
||||
def get_banner(self):
|
||||
return self.banner_image
|
|
@ -9,11 +9,8 @@ from wagtail_localize.fields import SynchronizedField, TranslatableField
|
|||
from networkapi.wagtailpages import utils
|
||||
from networkapi.wagtailpages.pagemodels import profiles
|
||||
from networkapi.wagtailpages.pagemodels.base import BasePage
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc import (
|
||||
constants,
|
||||
detail_page,
|
||||
library_page,
|
||||
)
|
||||
from networkapi.wagtailpages.pagemodels.libraries import constants as base_constants
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc import detail_page, library_page
|
||||
|
||||
|
||||
class RCCAuthorsIndexPage(
|
||||
|
@ -94,7 +91,7 @@ class RCCAuthorsIndexPage(
|
|||
def get_latest_author_rcc_entries(self, author_profile):
|
||||
author_articles = self.get_author_rcc_entries(author_profile)
|
||||
author_articles = author_articles.order_by("-original_publication_date")
|
||||
latest_articles = author_articles[: constants.LATEST_ARTICLES_COUNT]
|
||||
latest_articles = author_articles[: base_constants.LATEST_ARTICLES_COUNT]
|
||||
return latest_articles
|
||||
|
||||
def get_author_rcc_entries_count(self, author_profile):
|
||||
|
|
|
@ -1,134 +1,59 @@
|
|||
import typing
|
||||
from typing import Optional
|
||||
from functools import cached_property
|
||||
|
||||
from django.core import paginator
|
||||
from django.db import models
|
||||
from wagtail import images as wagtail_images
|
||||
from wagtail import models as wagtail_models
|
||||
from wagtail.admin import panels
|
||||
from wagtail.images import edit_handlers as image_panels
|
||||
from wagtail_localize.fields import SynchronizedField, TranslatableField
|
||||
|
||||
from networkapi.wagtailpages import utils
|
||||
from networkapi.wagtailpages.pagemodels import profiles as profile_models
|
||||
from networkapi.wagtailpages.pagemodels.base import BasePage
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc import (
|
||||
constants,
|
||||
detail_page,
|
||||
taxonomies,
|
||||
from networkapi.wagtailpages.pagemodels.libraries import (
|
||||
library_page as base_library_page,
|
||||
)
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc import detail_page, taxonomies
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc.forms import (
|
||||
RCCLibraryPageFilterForm,
|
||||
)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from django import http
|
||||
from django import template as django_template
|
||||
from django import forms
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
|
||||
class RCCLibraryPage(BasePage):
|
||||
max_count = 1
|
||||
|
||||
class RCCLibraryPage(base_library_page.BaseLibraryPage):
|
||||
parent_page_types = ["RCCLandingPage"]
|
||||
|
||||
subpage_types = ["RCCDetailPage"]
|
||||
|
||||
template = "pages/libraries/rcc/library_page.html"
|
||||
|
||||
SORT_CHOICES = constants.SORT_CHOICES
|
||||
@property
|
||||
def filter_form(self) -> "forms.Form":
|
||||
"""Form class used to filter detail pages for this page."""
|
||||
return RCCLibraryPageFilterForm
|
||||
|
||||
banner_image = models.ForeignKey(
|
||||
wagtail_images.get_image_model_string(),
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
|
||||
results_count = models.PositiveSmallIntegerField(
|
||||
default=10,
|
||||
help_text="Maximum number of results to be displayed per page.",
|
||||
)
|
||||
|
||||
content_panels = BasePage.content_panels + [
|
||||
image_panels.FieldPanel("banner_image"),
|
||||
]
|
||||
|
||||
settings_panels = BasePage.settings_panels + [panels.FieldPanel("results_count")]
|
||||
|
||||
translatable_fields = [
|
||||
# Content tab fields
|
||||
TranslatableField("title"),
|
||||
# Promote tab fields
|
||||
SynchronizedField("slug"),
|
||||
TranslatableField("seo_title"),
|
||||
SynchronizedField("show_in_menus"),
|
||||
TranslatableField("search_description"),
|
||||
SynchronizedField("search_image"),
|
||||
]
|
||||
|
||||
def get_context(self, request: "http.HttpRequest") -> "django_template.Context":
|
||||
search_query: str = request.GET.get("search", "")
|
||||
sort_value: str = request.GET.get("sort", "")
|
||||
sort: constants.SortOption = constants.SORT_CHOICES.get(sort_value, constants.SORT_NEWEST_FIRST)
|
||||
|
||||
filter_form = RCCLibraryPageFilterForm(request.GET, label_suffix="")
|
||||
@cached_property
|
||||
def detail_pages(self) -> "QuerySet[detail_page.RCCDetailPage]":
|
||||
"""Return the article detail pages that are children of this page."""
|
||||
return detail_page.RCCDetailPage.objects.live().public().filter(locale=wagtail_models.Locale.get_active())
|
||||
|
||||
@staticmethod
|
||||
def filter_detail_pages(
|
||||
pages: "QuerySet[detail_page.RCCDetailPage]", filter_form: "forms.Form"
|
||||
) -> "QuerySet[detail_page.RCCDetailPage]":
|
||||
"""Return the article detail pages that match the given filters in the form."""
|
||||
if filter_form.is_valid():
|
||||
filtered_author_ids: list[int] = filter_form.cleaned_data["authors"]
|
||||
filtered_content_type_ids: list[int] = filter_form.cleaned_data["content_types"]
|
||||
filtered_curricular_area_ids: list[int] = filter_form.cleaned_data["curricular_areas"]
|
||||
filtered_topic_ids: list[int] = filter_form.cleaned_data["topics"]
|
||||
author_profile_ids: list[int] = filter_form.cleaned_data["authors"]
|
||||
content_type_ids: list[int] = filter_form.cleaned_data["content_types"]
|
||||
curricular_area_ids: list[int] = filter_form.cleaned_data["curricular_areas"]
|
||||
topic_ids: list[int] = filter_form.cleaned_data["topics"]
|
||||
else:
|
||||
# If the form is not valid, we will not filter by any of the values.
|
||||
# This will result in all articles being displayed.
|
||||
filtered_author_ids = []
|
||||
filtered_content_type_ids = []
|
||||
filtered_curricular_area_ids = []
|
||||
filtered_topic_ids = []
|
||||
author_profile_ids = []
|
||||
content_type_ids = []
|
||||
curricular_area_ids = []
|
||||
topic_ids = []
|
||||
|
||||
searched_and_filtered_rcc_detail_pages = self._get_rcc_detail_pages(
|
||||
search=search_query,
|
||||
sort=sort,
|
||||
author_profile_ids=filtered_author_ids,
|
||||
content_type_ids=filtered_content_type_ids,
|
||||
curricular_area_ids=filtered_curricular_area_ids,
|
||||
topic_ids=filtered_topic_ids,
|
||||
)
|
||||
|
||||
rcc_detail_pages_paginator = paginator.Paginator(
|
||||
object_list=searched_and_filtered_rcc_detail_pages,
|
||||
per_page=self.results_count,
|
||||
allow_empty_first_page=True,
|
||||
)
|
||||
|
||||
page: Optional[str] = request.GET.get("page")
|
||||
rcc_detail_pages_page = rcc_detail_pages_paginator.get_page(page)
|
||||
|
||||
context: "django_template.Context" = super().get_context(request)
|
||||
context["search_query"] = search_query
|
||||
context["sort"] = sort
|
||||
context["form"] = filter_form
|
||||
context["rcc_detail_pages_count"] = rcc_detail_pages_paginator.count
|
||||
context["rcc_detail_pages"] = rcc_detail_pages_page
|
||||
return context
|
||||
|
||||
def _get_rcc_detail_pages(
|
||||
self,
|
||||
*,
|
||||
search: str = "",
|
||||
sort: constants.SortOption = constants.SORT_NEWEST_FIRST,
|
||||
author_profile_ids: Optional[list[int]] = None,
|
||||
content_type_ids: Optional[list[int]] = None,
|
||||
curricular_area_ids: Optional[list[int]] = None,
|
||||
topic_ids: Optional[list[int]] = None,
|
||||
):
|
||||
author_profile_ids = author_profile_ids or []
|
||||
content_type_ids = content_type_ids or []
|
||||
curricular_area_ids = curricular_area_ids or []
|
||||
topic_ids = topic_ids or []
|
||||
|
||||
rcc_detail_pages = detail_page.RCCDetailPage.objects.live().public()
|
||||
rcc_detail_pages = rcc_detail_pages.filter(locale=wagtail_models.Locale.get_active())
|
||||
rcc_detail_pages = pages
|
||||
|
||||
author_profiles = utils.get_rcc_authors(profile_models.Profile.objects.all())
|
||||
author_profiles = author_profiles.filter(id__in=author_profile_ids)
|
||||
|
@ -157,15 +82,4 @@ class RCCLibraryPage(BasePage):
|
|||
for topic in topics:
|
||||
rcc_detail_pages = rcc_detail_pages.filter(related_topics__topic__translation_key=topic.translation_key)
|
||||
|
||||
rcc_detail_pages = rcc_detail_pages.order_by(sort.order_by_value)
|
||||
|
||||
if search:
|
||||
rcc_detail_pages = rcc_detail_pages.search(
|
||||
search,
|
||||
order_by_relevance=False, # To preserve original ordering
|
||||
)
|
||||
|
||||
return rcc_detail_pages
|
||||
|
||||
def get_banner(self):
|
||||
return self.banner_image
|
||||
|
|
|
@ -9,8 +9,8 @@ from wagtail_localize.fields import SynchronizedField, TranslatableField
|
|||
from networkapi.wagtailpages import utils
|
||||
from networkapi.wagtailpages.pagemodels import profiles
|
||||
from networkapi.wagtailpages.pagemodels.base import BasePage
|
||||
from networkapi.wagtailpages.pagemodels.libraries import constants as base_constants
|
||||
from networkapi.wagtailpages.pagemodels.libraries.research_hub import (
|
||||
constants,
|
||||
detail_page,
|
||||
library_page,
|
||||
)
|
||||
|
@ -95,7 +95,7 @@ class ResearchAuthorsIndexPage(
|
|||
def get_latest_author_research(self, author_profile):
|
||||
author_research = self.get_author_research(author_profile)
|
||||
author_research = author_research.order_by("-original_publication_date")
|
||||
latest_research = author_research[: constants.LATEST_RESEARCH_COUNT_LIMIT]
|
||||
latest_research = author_research[: base_constants.LATEST_ARTICLES_COUNT]
|
||||
return latest_research
|
||||
|
||||
def get_author_research_count(self, author_profile):
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import collections
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# We don't want to expose the actual database column value that we use for sorting.
|
||||
# Therefore, we need a separate value that is used in the form and url.
|
||||
SortOption = collections.namedtuple("SortOption", ["label", "value", "order_by_value"])
|
||||
|
||||
SORT_NEWEST_FIRST = SortOption(
|
||||
label=_("Newest first"),
|
||||
value="newest-first",
|
||||
order_by_value="-original_publication_date",
|
||||
)
|
||||
SORT_OLDEST_FIRST = SortOption(
|
||||
label=_("Oldest first"),
|
||||
value="oldest-first",
|
||||
order_by_value="original_publication_date",
|
||||
)
|
||||
SORT_ALPHABETICAL = SortOption(
|
||||
label=_("Alphabetical (A-Z)"),
|
||||
value="alphabetical",
|
||||
order_by_value="title",
|
||||
)
|
||||
SORT_ALPHABETICAL_REVERSED = SortOption(
|
||||
label=_("Alphabetical (Z-A)"),
|
||||
value="alphabetical-reversed",
|
||||
order_by_value="-title",
|
||||
)
|
||||
SORT_CHOICES = {
|
||||
SORT_NEWEST_FIRST.value: SORT_NEWEST_FIRST,
|
||||
SORT_OLDEST_FIRST.value: SORT_OLDEST_FIRST,
|
||||
SORT_ALPHABETICAL.value: SORT_ALPHABETICAL,
|
||||
SORT_ALPHABETICAL_REVERSED.value: SORT_ALPHABETICAL_REVERSED,
|
||||
}
|
||||
|
||||
LATEST_RESEARCH_COUNT_LIMIT = 3
|
|
@ -48,7 +48,7 @@ class ResearchLibraryPageFilterForm(forms.Form):
|
|||
choices=_get_topic_options,
|
||||
label=pgettext_lazy("Filter form field label", "Topics"),
|
||||
)
|
||||
years = forms.ChoiceField(
|
||||
year = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=_get_year_options,
|
||||
widget=forms.RadioSelect(attrs={"class": "rh-radio"}),
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
import typing
|
||||
from functools import cached_property
|
||||
from typing import Optional
|
||||
|
||||
from django.core import paginator
|
||||
from django.db import models
|
||||
from wagtail import images as wagtail_images
|
||||
from wagtail import models as wagtail_models
|
||||
from wagtail.admin import panels
|
||||
from wagtail.images import edit_handlers as image_panels
|
||||
from wagtail_localize.fields import SynchronizedField, TranslatableField
|
||||
|
||||
from networkapi.wagtailpages import utils
|
||||
from networkapi.wagtailpages.pagemodels import profiles as profile_models
|
||||
from networkapi.wagtailpages.pagemodels.base import BasePage
|
||||
from networkapi.wagtailpages.pagemodels.libraries import (
|
||||
library_page as base_library_page,
|
||||
)
|
||||
from networkapi.wagtailpages.pagemodels.libraries.research_hub import (
|
||||
constants,
|
||||
detail_page,
|
||||
taxonomies,
|
||||
)
|
||||
|
@ -22,110 +18,46 @@ from networkapi.wagtailpages.pagemodels.libraries.research_hub.forms import (
|
|||
)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from django import http
|
||||
from django import template as django_template
|
||||
from django import forms
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
|
||||
class ResearchLibraryPage(BasePage):
|
||||
max_count = 1
|
||||
|
||||
class ResearchLibraryPage(base_library_page.BaseLibraryPage):
|
||||
parent_page_types = ["ResearchLandingPage"]
|
||||
|
||||
subpage_types = ["ResearchDetailPage"]
|
||||
|
||||
template = "pages/libraries/research_hub/library_page.html"
|
||||
|
||||
SORT_CHOICES = constants.SORT_CHOICES
|
||||
@property
|
||||
def filter_form(self) -> "forms.Form":
|
||||
"""Form class used to filter detail pages for this page."""
|
||||
return ResearchLibraryPageFilterForm
|
||||
|
||||
banner_image = models.ForeignKey(
|
||||
wagtail_images.get_image_model_string(),
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
@cached_property
|
||||
def detail_pages(self) -> "QuerySet[detail_page.ResearchDetailPage]":
|
||||
"""Return the article detail pages that are children of this page."""
|
||||
return detail_page.ResearchDetailPage.objects.live().public().filter(locale=wagtail_models.Locale.get_active())
|
||||
|
||||
results_count = models.PositiveSmallIntegerField(
|
||||
default=10,
|
||||
help_text="Maximum number of results to be displayed per page.",
|
||||
)
|
||||
|
||||
content_panels = BasePage.content_panels + [
|
||||
image_panels.FieldPanel("banner_image"),
|
||||
]
|
||||
|
||||
settings_panels = BasePage.settings_panels + [panels.FieldPanel("results_count")]
|
||||
|
||||
translatable_fields = [
|
||||
# Content tab fields
|
||||
TranslatableField("title"),
|
||||
# Promote tab fields
|
||||
SynchronizedField("slug"),
|
||||
TranslatableField("seo_title"),
|
||||
SynchronizedField("show_in_menus"),
|
||||
TranslatableField("search_description"),
|
||||
SynchronizedField("search_image"),
|
||||
]
|
||||
|
||||
def get_context(self, request: "http.HttpRequest") -> "django_template.Context":
|
||||
search_query: str = request.GET.get("search", "")
|
||||
sort_value: str = request.GET.get("sort", "")
|
||||
sort: constants.SortOption = constants.SORT_CHOICES.get(sort_value, constants.SORT_NEWEST_FIRST)
|
||||
|
||||
filter_form = ResearchLibraryPageFilterForm(request.GET, label_suffix="")
|
||||
@staticmethod
|
||||
def filter_detail_pages(
|
||||
pages: "QuerySet[detail_page.ResearchDetailPage]", filter_form: "forms.Form"
|
||||
) -> "QuerySet[detail_page.ResearchDetailPage]":
|
||||
"""Return the article detail pages that match the given filters in the form."""
|
||||
if filter_form.is_valid():
|
||||
filtered_author_ids: list[int] = filter_form.cleaned_data["authors"]
|
||||
filtered_topic_ids: list[int] = filter_form.cleaned_data["topics"]
|
||||
filtered_region_ids: list[int] = filter_form.cleaned_data["regions"]
|
||||
filtered_year: Optional[int] = filter_form.cleaned_data["years"]
|
||||
author_profile_ids: list[int] = filter_form.cleaned_data["authors"]
|
||||
topic_ids: list[int] = filter_form.cleaned_data["topics"]
|
||||
region_ids: list[int] = filter_form.cleaned_data["regions"]
|
||||
year: Optional[int] = filter_form.cleaned_data["year"]
|
||||
else:
|
||||
# If the form is not valid, we will not filter by any of the values.
|
||||
# This will result in all research being displayed.
|
||||
filtered_author_ids = []
|
||||
filtered_topic_ids = []
|
||||
filtered_region_ids = []
|
||||
filtered_year = None
|
||||
author_profile_ids = []
|
||||
topic_ids = []
|
||||
region_ids = []
|
||||
year = None
|
||||
|
||||
searched_and_filtered_research_detail_pages = self._get_research_detail_pages(
|
||||
search=search_query,
|
||||
sort=sort,
|
||||
author_profile_ids=filtered_author_ids,
|
||||
topic_ids=filtered_topic_ids,
|
||||
region_ids=filtered_region_ids,
|
||||
year=filtered_year,
|
||||
)
|
||||
research_detail_pages_paginator = paginator.Paginator(
|
||||
object_list=searched_and_filtered_research_detail_pages,
|
||||
per_page=self.results_count,
|
||||
allow_empty_first_page=True,
|
||||
)
|
||||
|
||||
page: Optional[str] = request.GET.get("page")
|
||||
research_detail_pages_page = research_detail_pages_paginator.get_page(page)
|
||||
|
||||
context: "django_template.Context" = super().get_context(request)
|
||||
context["search_query"] = search_query
|
||||
context["sort"] = sort
|
||||
context["form"] = filter_form
|
||||
context["research_detail_pages_count"] = research_detail_pages_paginator.count
|
||||
context["research_detail_pages"] = research_detail_pages_page
|
||||
return context
|
||||
|
||||
def _get_research_detail_pages(
|
||||
self,
|
||||
*,
|
||||
search: str = "",
|
||||
sort: constants.SortOption = constants.SORT_NEWEST_FIRST,
|
||||
author_profile_ids: Optional[list[int]] = None,
|
||||
topic_ids: Optional[list[int]] = None,
|
||||
region_ids: Optional[list[int]] = None,
|
||||
year: Optional[int] = None,
|
||||
):
|
||||
author_profile_ids = author_profile_ids or []
|
||||
topic_ids = topic_ids or []
|
||||
region_ids = region_ids or []
|
||||
|
||||
research_detail_pages = detail_page.ResearchDetailPage.objects.live().public()
|
||||
research_detail_pages = research_detail_pages.filter(locale=wagtail_models.Locale.get_active())
|
||||
research_detail_pages = pages
|
||||
|
||||
author_profiles = utils.get_research_authors(profile_models.Profile.objects.all())
|
||||
author_profiles = author_profiles.filter(id__in=author_profile_ids)
|
||||
|
@ -153,15 +85,4 @@ class ResearchLibraryPage(BasePage):
|
|||
if year:
|
||||
research_detail_pages = research_detail_pages.filter(original_publication_date__year=year)
|
||||
|
||||
research_detail_pages = research_detail_pages.order_by(sort.order_by_value)
|
||||
|
||||
if search:
|
||||
research_detail_pages = research_detail_pages.search(
|
||||
search,
|
||||
order_by_relevance=False, # To preserve original ordering
|
||||
)
|
||||
|
||||
return research_detail_pages
|
||||
|
||||
def get_banner(self):
|
||||
return self.banner_image
|
||||
|
|
|
@ -11,7 +11,10 @@ from networkapi.wagtailpages.factory.libraries.rcc import relations as relations
|
|||
from networkapi.wagtailpages.factory.libraries.rcc import (
|
||||
taxonomies as taxonomies_factory,
|
||||
)
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc import constants
|
||||
from networkapi.wagtailpages.pagemodels.libraries import constants
|
||||
from networkapi.wagtailpages.pagemodels.libraries.rcc.forms import (
|
||||
RCCLibraryPageFilterForm,
|
||||
)
|
||||
from networkapi.wagtailpages.tests.libraries.rcc import base as rcc_test_base
|
||||
from networkapi.wagtailpages.tests.libraries.rcc import utils as rcc_test_utils
|
||||
|
||||
|
@ -21,7 +24,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
with open(os.devnull, "w") as f:
|
||||
management.call_command("update_index", verbosity=0, stdout=f)
|
||||
|
||||
def test_get_rcc_detail_pages(self):
|
||||
def testget_sorted_filtered_detail_pages(self):
|
||||
detail_page_1 = detail_page_factory.RCCDetailPageFactory(
|
||||
parent=self.library_page,
|
||||
)
|
||||
|
@ -29,13 +32,13 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
parent=self.library_page,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages()
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 2)
|
||||
self.assertIn(detail_page_1, rcc_detail_pages)
|
||||
self.assertIn(detail_page_2, rcc_detail_pages)
|
||||
|
||||
def test_get_rcc_detail_pages_with_translation_aliases(self):
|
||||
def testget_sorted_filtered_detail_pages_with_translation_aliases(self):
|
||||
detail_page_1 = detail_page_factory.RCCDetailPageFactory(
|
||||
parent=self.library_page,
|
||||
)
|
||||
|
@ -46,7 +49,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
fr_detail_page_1 = detail_page_1.get_translation(self.fr_locale)
|
||||
fr_detail_page_2 = detail_page_2.get_translation(self.fr_locale)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages()
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 2)
|
||||
self.assertIn(detail_page_1, rcc_detail_pages)
|
||||
|
@ -63,7 +66,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
)
|
||||
self.make_page_private(private_detail_page)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages()
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(public_detail_page, rcc_detail_pages)
|
||||
self.assertNotIn(private_detail_page, rcc_detail_pages)
|
||||
|
@ -78,7 +81,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
original_publication_date=rcc_test_utils.days_ago(1),
|
||||
)
|
||||
|
||||
rcc_detail_pages = list(self.library_page._get_rcc_detail_pages(sort=constants.SORT_NEWEST_FIRST))
|
||||
rcc_detail_pages = list(self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_NEWEST_FIRST))
|
||||
|
||||
newest_page_index = rcc_detail_pages.index(newest_page)
|
||||
oldest_page_index = rcc_detail_pages.index(oldest_page)
|
||||
|
@ -94,7 +97,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
original_publication_date=rcc_test_utils.days_ago(1),
|
||||
)
|
||||
|
||||
rcc_detail_pages = list(self.library_page._get_rcc_detail_pages(sort=constants.SORT_OLDEST_FIRST))
|
||||
rcc_detail_pages = list(self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_OLDEST_FIRST))
|
||||
|
||||
newest_page_index = rcc_detail_pages.index(newest_page)
|
||||
oldest_page_index = rcc_detail_pages.index(oldest_page)
|
||||
|
@ -110,7 +113,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
title="Banana",
|
||||
)
|
||||
|
||||
rcc_detail_pages = list(self.library_page._get_rcc_detail_pages(sort=constants.SORT_ALPHABETICAL))
|
||||
rcc_detail_pages = list(self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_ALPHABETICAL))
|
||||
|
||||
apple_page_index = rcc_detail_pages.index(apple_page)
|
||||
banana_page_index = rcc_detail_pages.index(banana_page)
|
||||
|
@ -127,13 +130,15 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
title="Banana",
|
||||
)
|
||||
|
||||
rcc_detail_pages = list(self.library_page._get_rcc_detail_pages(sort=constants.SORT_ALPHABETICAL_REVERSED))
|
||||
rcc_detail_pages = list(
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_ALPHABETICAL_REVERSED)
|
||||
)
|
||||
|
||||
apple_page_index = rcc_detail_pages.index(apple_page)
|
||||
banana_page_index = rcc_detail_pages.index(banana_page)
|
||||
self.assertLess(banana_page_index, apple_page_index)
|
||||
|
||||
def test_get_rcc_detail_pages_sort_default(self):
|
||||
def testget_sorted_filtered_detail_pages_sort_default(self):
|
||||
|
||||
detail_page_factory.RCCDetailPageFactory(
|
||||
parent=self.library_page,
|
||||
|
@ -144,8 +149,10 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
original_publication_date=rcc_test_utils.days_ago(1),
|
||||
)
|
||||
|
||||
default_sort_detail_pages = list(self.library_page._get_rcc_detail_pages())
|
||||
newest_first_detail_pages = list(self.library_page._get_rcc_detail_pages(sort=constants.SORT_NEWEST_FIRST))
|
||||
default_sort_detail_pages = list(self.library_page.get_sorted_filtered_detail_pages())
|
||||
newest_first_detail_pages = list(
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_NEWEST_FIRST)
|
||||
)
|
||||
|
||||
self.assertEqual(default_sort_detail_pages, newest_first_detail_pages)
|
||||
|
||||
|
@ -155,7 +162,7 @@ class TestRCCLibraryPage(rcc_test_base.RCCTestCase):
|
|||
for _ in range(6):
|
||||
detail_page_factory.RCCDetailPageFactory(parent=self.library_page)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages()
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
|
||||
rcc_detail_pages_paginator = paginator.Paginator(
|
||||
object_list=rcc_detail_pages,
|
||||
|
@ -189,7 +196,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
collaborators="",
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
self.assertNotIn(banana_page, rcc_detail_pages)
|
||||
|
@ -210,7 +217,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
collaborators="",
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -232,7 +239,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
collaborators="",
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -254,7 +261,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
collaborators="Banana",
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -290,7 +297,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
relations_factory.RCCAuthorRelationFactory(detail_page=banana_page, author_profile=banana_profile)
|
||||
self.update_index()
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -326,7 +333,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
)
|
||||
self.update_index()
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -362,7 +369,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
)
|
||||
self.update_index()
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -394,7 +401,7 @@ class TestRCCLibraryPageSearch(TestRCCLibraryPage):
|
|||
relations_factory.RCCDetailPageRCCTopicRelationFactory(detail_page=banana_page, topic=banana_topic)
|
||||
self.update_index()
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(search="Apple")
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 1)
|
||||
self.assertIn(apple_page, rcc_detail_pages)
|
||||
|
@ -415,7 +422,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
detail_page_2.authors.first().author_profile,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(author_profile_ids=[author_profile.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"authors": [author_profile.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_2, rcc_detail_pages)
|
||||
|
@ -441,7 +449,7 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
)
|
||||
|
||||
# Only show the page where both profiles are authors
|
||||
rcc_detail_pages = response.context["rcc_detail_pages"]
|
||||
rcc_detail_pages = response.context["detail_pages"]
|
||||
self.assertNotIn(detail_page_1, rcc_detail_pages)
|
||||
self.assertIn(detail_page_2, rcc_detail_pages)
|
||||
|
||||
|
@ -474,7 +482,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
self.assertEqual(profile.translation_key, profile_fr.translation_key)
|
||||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
rcc_detail_pages = self.library_page.localized._get_rcc_detail_pages(author_profile_ids=[profile_fr.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"authors": [profile_fr.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1_fr, rcc_detail_pages)
|
||||
self.assertIn(detail_page_2_fr, rcc_detail_pages)
|
||||
|
@ -493,7 +502,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
related_content_types__content_type=content_type_B,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(content_type_ids=[content_type_A.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"content_types": [content_type_A.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_A, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_B, rcc_detail_pages)
|
||||
|
@ -510,7 +520,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
related_curricular_areas__curricular_area=curricular_area_B,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(curricular_area_ids=[curricular_area_A.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"curricular_areas": [curricular_area_A.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_A, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_B, rcc_detail_pages)
|
||||
|
@ -527,7 +538,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
related_topics__topic=topic_B,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(topic_ids=[topic_A.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"topics": [topic_A.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_A, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_B, rcc_detail_pages)
|
||||
|
@ -547,9 +559,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
related_content_types__content_type=content_type_A,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(
|
||||
content_type_ids=[content_type_A.id, content_type_B.id]
|
||||
)
|
||||
filter_form = RCCLibraryPageFilterForm(data={"content_types": [content_type_A.id, content_type_B.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_2, rcc_detail_pages)
|
||||
|
@ -569,9 +580,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
related_curricular_areas__curricular_area=curricular_area_A,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(
|
||||
curricular_area_ids=[curricular_area_A.id, curricular_area_B.id]
|
||||
)
|
||||
filter_form = RCCLibraryPageFilterForm(data={"curricular_areas": [curricular_area_A.id, curricular_area_B.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_2, rcc_detail_pages)
|
||||
|
@ -589,7 +599,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
related_topics__topic=topic_A,
|
||||
)
|
||||
|
||||
rcc_detail_pages = self.library_page._get_rcc_detail_pages(topic_ids=[topic_A.id, topic_B.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"topics": [topic_A.id, topic_B.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, rcc_detail_pages)
|
||||
self.assertNotIn(detail_page_2, rcc_detail_pages)
|
||||
|
@ -631,7 +642,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
# Filter for the translated content type
|
||||
rcc_detail_pages = self.library_page.localized._get_rcc_detail_pages(content_type_ids=[content_type_fr.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"content_types": [content_type_fr.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
# We should see both pages, even though the first one is not associated with the
|
||||
# translated content type
|
||||
|
@ -678,9 +690,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
# Filter for the translated curricular area
|
||||
rcc_detail_pages = self.library_page.localized._get_rcc_detail_pages(
|
||||
curricular_area_ids=[curricular_area_fr.id]
|
||||
)
|
||||
filter_form = RCCLibraryPageFilterForm(data={"curricular_area": [curricular_area_fr.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
# We should see both pages, even though the first one is not associated with the
|
||||
# translated curricular area
|
||||
|
@ -719,7 +730,8 @@ class TestRCCLibraryPageFilters(TestRCCLibraryPage):
|
|||
self.assertEqual(topic.translation_key, topic_fr.translation_key)
|
||||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
rcc_detail_pages = self.library_page.localized._get_rcc_detail_pages(topic_ids=[topic_fr.id])
|
||||
filter_form = RCCLibraryPageFilterForm(data={"topics": [topic_fr.id]})
|
||||
rcc_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertEqual(len(rcc_detail_pages), 2)
|
||||
self.assertIn(detail_page_1_fr, rcc_detail_pages)
|
||||
|
|
|
@ -216,7 +216,7 @@ class ResearchLibraryPageFilterFormTestCase(research_test_base.ResearchHubTestCa
|
|||
self.assertCountEqual(form.fields["topics"].choices, [(t.id, t.name) for t in topics])
|
||||
|
||||
def test_form_years(self):
|
||||
"""Test that the form years field is populated with the correct choices."""
|
||||
"""Test that the form year field is populated with the correct choices."""
|
||||
years = [timezone.now().year, timezone.now().year - 1]
|
||||
detail_page_factory.ResearchDetailPageFactory(
|
||||
parent=self.library_page,
|
||||
|
@ -228,7 +228,7 @@ class ResearchLibraryPageFilterFormTestCase(research_test_base.ResearchHubTestCa
|
|||
)
|
||||
|
||||
form = ResearchLibraryPageFilterForm()
|
||||
self.assertCountEqual(form.fields["years"].choices, [("", "Any")] + [(y, y) for y in years])
|
||||
self.assertCountEqual(form.fields["year"].choices, [("", "Any")] + [(y, y) for y in years])
|
||||
|
||||
def test_form_regions(self):
|
||||
"""Test that the form regions field is populated with the correct choices."""
|
||||
|
|
|
@ -14,7 +14,10 @@ from networkapi.wagtailpages.factory.libraries.research_hub import (
|
|||
from networkapi.wagtailpages.factory.libraries.research_hub import (
|
||||
taxonomies as taxonomies_factory,
|
||||
)
|
||||
from networkapi.wagtailpages.pagemodels.libraries.research_hub import constants
|
||||
from networkapi.wagtailpages.pagemodels.libraries import constants
|
||||
from networkapi.wagtailpages.pagemodels.libraries.research_hub.forms import (
|
||||
ResearchLibraryPageFilterForm,
|
||||
)
|
||||
from networkapi.wagtailpages.tests.libraries.research_hub import (
|
||||
base as research_test_base,
|
||||
)
|
||||
|
@ -36,7 +39,7 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
parent=self.library_page,
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages()
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 2)
|
||||
self.assertIn(detail_page_1, research_detail_pages)
|
||||
|
@ -53,7 +56,7 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
fr_detail_page_1 = detail_page_1.get_translation(self.fr_locale)
|
||||
fr_detail_page_2 = detail_page_2.get_translation(self.fr_locale)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages()
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 2)
|
||||
self.assertIn(detail_page_1, research_detail_pages)
|
||||
|
@ -70,7 +73,7 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
)
|
||||
self.make_page_private(private_detail_page)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages()
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(public_detail_page, research_detail_pages)
|
||||
self.assertNotIn(private_detail_page, research_detail_pages)
|
||||
|
@ -85,7 +88,9 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
original_publication_date=research_test_utils.days_ago(1),
|
||||
)
|
||||
|
||||
research_detail_pages = list(self.library_page._get_research_detail_pages(sort=constants.SORT_NEWEST_FIRST))
|
||||
research_detail_pages = list(
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_NEWEST_FIRST)
|
||||
)
|
||||
|
||||
newest_page_index = research_detail_pages.index(newest_page)
|
||||
oldest_page_index = research_detail_pages.index(oldest_page)
|
||||
|
@ -101,7 +106,9 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
original_publication_date=research_test_utils.days_ago(1),
|
||||
)
|
||||
|
||||
research_detail_pages = list(self.library_page._get_research_detail_pages(sort=constants.SORT_OLDEST_FIRST))
|
||||
research_detail_pages = list(
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_OLDEST_FIRST)
|
||||
)
|
||||
|
||||
newest_page_index = research_detail_pages.index(newest_page)
|
||||
oldest_page_index = research_detail_pages.index(oldest_page)
|
||||
|
@ -117,7 +124,9 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
title="Banana",
|
||||
)
|
||||
|
||||
research_detail_pages = list(self.library_page._get_research_detail_pages(sort=constants.SORT_ALPHABETICAL))
|
||||
research_detail_pages = list(
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_ALPHABETICAL)
|
||||
)
|
||||
|
||||
apple_page_index = research_detail_pages.index(apple_page)
|
||||
banana_page_index = research_detail_pages.index(banana_page)
|
||||
|
@ -135,7 +144,7 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
)
|
||||
|
||||
research_detail_pages = list(
|
||||
self.library_page._get_research_detail_pages(sort=constants.SORT_ALPHABETICAL_REVERSED)
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_ALPHABETICAL_REVERSED)
|
||||
)
|
||||
|
||||
apple_page_index = research_detail_pages.index(apple_page)
|
||||
|
@ -153,9 +162,9 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
original_publication_date=research_test_utils.days_ago(1),
|
||||
)
|
||||
|
||||
default_sort_detail_pages = list(self.library_page._get_research_detail_pages())
|
||||
default_sort_detail_pages = list(self.library_page.get_sorted_filtered_detail_pages())
|
||||
newest_first_detail_pages = list(
|
||||
self.library_page._get_research_detail_pages(sort=constants.SORT_NEWEST_FIRST)
|
||||
self.library_page.get_sorted_filtered_detail_pages(sort=constants.SORT_NEWEST_FIRST)
|
||||
)
|
||||
|
||||
self.assertEqual(default_sort_detail_pages, newest_first_detail_pages)
|
||||
|
@ -166,7 +175,7 @@ class TestResearchLibraryPage(research_test_base.ResearchHubTestCase):
|
|||
for _ in range(6):
|
||||
detail_page_factory.ResearchDetailPageFactory(parent=self.library_page)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages()
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages()
|
||||
|
||||
research_detail_pages_paginator = paginator.Paginator(
|
||||
object_list=research_detail_pages,
|
||||
|
@ -200,7 +209,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
collaborators="",
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
self.assertNotIn(banana_page, research_detail_pages)
|
||||
|
@ -221,7 +230,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
collaborators="",
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
|
@ -243,7 +252,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
collaborators="",
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
|
@ -265,7 +274,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
collaborators="Banana",
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
|
@ -301,7 +310,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
relations_factory.ResearchAuthorRelationFactory(detail_page=banana_page, author_profile=banana_profile)
|
||||
self.update_index()
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
|
@ -335,7 +344,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
relations_factory.ResearchDetailPageResearchTopicRelationFactory(detail_page=banana_page, topic=banana_topic)
|
||||
self.update_index()
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
|
@ -365,7 +374,7 @@ class TestResearchLibraryPageSearch(TestResearchLibraryPage):
|
|||
)
|
||||
self.update_index()
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(search="Apple")
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(search_query="Apple")
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 1)
|
||||
self.assertIn(apple_page, research_detail_pages)
|
||||
|
@ -386,7 +395,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
detail_page_2.authors.first().author_profile,
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(author_profile_ids=[author_profile.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"authors": [author_profile.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, research_detail_pages)
|
||||
self.assertNotIn(detail_page_2, research_detail_pages)
|
||||
|
@ -412,7 +422,7 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
)
|
||||
|
||||
# Only show the page where both profiles are authors
|
||||
research_detail_pages = response.context["research_detail_pages"]
|
||||
research_detail_pages = response.context["detail_pages"]
|
||||
self.assertNotIn(detail_page_1, research_detail_pages)
|
||||
self.assertIn(detail_page_2, research_detail_pages)
|
||||
|
||||
|
@ -445,9 +455,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
self.assertEqual(profile.translation_key, profile_fr.translation_key)
|
||||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
research_detail_pages = self.library_page.localized._get_research_detail_pages(
|
||||
author_profile_ids=[profile_fr.id]
|
||||
)
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"authors": [profile_fr.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1_fr, research_detail_pages)
|
||||
self.assertIn(detail_page_2_fr, research_detail_pages)
|
||||
|
@ -466,7 +475,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
related_topics__topic=topic_B,
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(topic_ids=[topic_A.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"topics": [topic_A.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_A, research_detail_pages)
|
||||
self.assertNotIn(detail_page_B, research_detail_pages)
|
||||
|
@ -484,7 +494,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
related_topics__topic=topic_A,
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(topic_ids=[topic_A.id, topic_B.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"topics": [topic_A.id, topic_B.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, research_detail_pages)
|
||||
self.assertNotIn(detail_page_2, research_detail_pages)
|
||||
|
@ -518,7 +529,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
self.assertEqual(topic.translation_key, topic_fr.translation_key)
|
||||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
research_detail_pages = self.library_page.localized._get_research_detail_pages(topic_ids=[topic_fr.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"topics": [topic_fr.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 2)
|
||||
self.assertIn(detail_page_1_fr, research_detail_pages)
|
||||
|
@ -538,7 +550,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
related_regions__region=region_B,
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(region_ids=[region_A.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"regions": [region_A.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_A, research_detail_pages)
|
||||
self.assertNotIn(detail_page_B, research_detail_pages)
|
||||
|
@ -556,7 +569,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
related_regions__region=region_A,
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(region_ids=[region_A.id, region_B.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"regions": [region_A.id, region_B.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, research_detail_pages)
|
||||
self.assertNotIn(detail_page_2, research_detail_pages)
|
||||
|
@ -590,7 +604,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
self.assertEqual(region.translation_key, region_fr.translation_key)
|
||||
translation.activate(self.fr_locale.language_code)
|
||||
|
||||
research_detail_pages = self.library_page.localized._get_research_detail_pages(region_ids=[region_fr.id])
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"regions": [region_fr.id]})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertEqual(len(research_detail_pages), 2)
|
||||
self.assertIn(detail_page_1_fr, research_detail_pages)
|
||||
|
@ -608,7 +623,8 @@ class TestResearchLibraryPageFilters(TestResearchLibraryPage):
|
|||
original_publication_date=datetime.date(year_1 + 1, 6, 1),
|
||||
)
|
||||
|
||||
research_detail_pages = self.library_page._get_research_detail_pages(year=year_1)
|
||||
filter_form = ResearchLibraryPageFilterForm(data={"year": year_1})
|
||||
research_detail_pages = self.library_page.get_sorted_filtered_detail_pages(filter_form=filter_form)
|
||||
|
||||
self.assertIn(detail_page_1, research_detail_pages)
|
||||
self.assertNotIn(detail_page_2, research_detail_pages)
|
||||
|
|
Загрузка…
Ссылка в новой задаче