Skip to content

Commit ba8f229

Browse files
committed
Refactors feed titles and descriptions, add pagination to feed and contribution pages
Updates feed titles and descriptions for clarity and consistency, removing redundant information about feed types. Also modifies the contribute page to include pagination and increase the number of publications shown. Finally, it updates expected XML files for feed generation tests.
1 parent 9d04938 commit ba8f229

File tree

10 files changed

+190
-38
lines changed

10 files changed

+190
-38
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6464

6565
### Changed
6666

67+
- **Contribution page pagination** - Added full pagination support to the contribution page (`/contribute/`) with:
68+
- Configurable page size (default 50, min 10, max 200 works per page)
69+
- User-selectable page size dropdown with automatic form submission
70+
- Full pagination controls at top and bottom (First, Previous, page numbers, Next, Last)
71+
- Shows current range (e.g., "Showing 1 to 50 of 150 works")
72+
- Fixed variable name bugs (`publication``work` throughout template)
73+
- Reuses the same pagination layout as works listing page for consistency
6774
- **Model terminology alignment** - Renamed base entity from "publications" to "works" throughout the codebase to align with [OpenAlex terminology](https://docs.openalex.org/api-entities/works):
6875
- Django app renamed from `publications/` to `works/`
6976
- `Publication` model renamed to `Work`

optimap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "0.10.0"
1+
__version__ = "0.11.0"
22
VERSION = __version__
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"><title>OPTIMAP - Latest Publications (ATOM)</title><link href="http://testserver/" rel="alternate"/><link href="http://testserver/api/v1/feeds/optimap-global.atom" rel="self"/><id>http://testserver/</id><updated>2025-10-27T21:43:33.089797+00:00</updated><author><name>OPTIMAP</name><email>[email protected]</email><uri>https://optimap.science</uri></author><entry><title>LineString Test</title><link href="http://127.0.0.1:8000/work/10.1234/test-doi-3/" rel="alternate"/><published>2023-05-20T00:00:00+00:00</published><updated>2025-10-27T21:43:33.089797+00:00</updated><id>http://127.0.0.1:8000/work/10.1234/test-doi-3/</id><summary type="html">Publication with a linestring inside a collection.</summary><georss:line>45.0 5.0 46.0 6.0 45.5 7.0</georss:line></entry><entry><title>Polygon Test</title><link href="http://127.0.0.1:8000/work/10.1234/test-doi-2/" rel="alternate"/><published>2023-05-15T00:00:00+00:00</published><updated>2025-10-27T21:43:33.087185+00:00</updated><id>http://127.0.0.1:8000/work/10.1234/test-doi-2/</id><summary type="html">Publication with a polygon inside a collection.</summary><georss:polygon>50.0 10.0 51.0 11.0 50.0 12.0 50.0 10.0</georss:polygon></entry><entry><title>Point Test</title><link href="http://127.0.0.1:8000/work/10.1234/test-doi-1/" rel="alternate"/><published>2023-05-10T00:00:00+00:00</published><updated>2025-10-27T21:43:33.082750+00:00</updated><id>http://127.0.0.1:8000/work/10.1234/test-doi-1/</id><summary type="html">Publication with a single point inside a collection.</summary><georss:point>41.8902 12.4924</georss:point></entry></feed>
2+
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"><title>OPTIMAP - Latest works</title><link href="http://testserver/" rel="alternate"/><link href="http://testserver/api/v1/feeds/optimap-global.atom" rel="self"/><id>http://testserver/</id><updated>2025-10-27T21:43:33.089797+00:00</updated><author><name>OPTIMAP</name><email>[email protected]</email><uri>https://optimap.science</uri></author><entry><title>LineString Test</title><link href="http://127.0.0.1:8000/work/10.1234/test-doi-3/" rel="alternate"/><published>2023-05-20T00:00:00+00:00</published><updated>2025-10-27T21:43:33.089797+00:00</updated><id>http://127.0.0.1:8000/work/10.1234/test-doi-3/</id><summary type="html">Publication with a linestring inside a collection.</summary><georss:line>45.0 5.0 46.0 6.0 45.5 7.0</georss:line></entry><entry><title>Polygon Test</title><link href="http://127.0.0.1:8000/work/10.1234/test-doi-2/" rel="alternate"/><published>2023-05-15T00:00:00+00:00</published><updated>2025-10-27T21:43:33.087185+00:00</updated><id>http://127.0.0.1:8000/work/10.1234/test-doi-2/</id><summary type="html">Publication with a polygon inside a collection.</summary><georss:polygon>50.0 10.0 51.0 11.0 50.0 12.0 50.0 10.0</georss:polygon></entry><entry><title>Point Test</title><link href="http://127.0.0.1:8000/work/10.1234/test-doi-1/" rel="alternate"/><published>2023-05-10T00:00:00+00:00</published><updated>2025-10-27T21:43:33.082750+00:00</updated><id>http://127.0.0.1:8000/work/10.1234/test-doi-1/</id><summary type="html">Publication with a single point inside a collection.</summary><georss:point>41.8902 12.4924</georss:point></entry></feed>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"><channel><title>OPTIMAP - Latest Publications (GEORSS)</title><link>http://testserver/</link><description>Latest research publications with geographic data from OPTIMAP.</description><atom:link href="http://testserver/api/v1/feeds/optimap-global.rss" rel="self"/><language>en-us</language><lastBuildDate>Mon, 27 Oct 2025 21:43:33 +0000</lastBuildDate><atom:link href="http://testserver/api/v1/feeds/optimap-global.rss" rel="self" type="application/rss+xml"/><item><title>LineString Test</title><link>http://127.0.0.1:8000/work/10.1234/test-doi-3/</link><description>Publication with a linestring inside a collection.</description><pubDate>Sat, 20 May 2023 00:00:00 +0000</pubDate><guid>http://127.0.0.1:8000/work/10.1234/test-doi-3/</guid><georss:line>45.0 5.0 46.0 6.0 45.5 7.0</georss:line></item><item><title>Polygon Test</title><link>http://127.0.0.1:8000/work/10.1234/test-doi-2/</link><description>Publication with a polygon inside a collection.</description><pubDate>Mon, 15 May 2023 00:00:00 +0000</pubDate><guid>http://127.0.0.1:8000/work/10.1234/test-doi-2/</guid><georss:polygon>50.0 10.0 51.0 11.0 50.0 12.0 50.0 10.0</georss:polygon></item><item><title>Point Test</title><link>http://127.0.0.1:8000/work/10.1234/test-doi-1/</link><description>Publication with a single point inside a collection.</description><pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate><guid>http://127.0.0.1:8000/work/10.1234/test-doi-1/</guid><georss:point>41.8902 12.4924</georss:point></item></channel></rss>
2+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"><channel><title>OPTIMAP - Latest works</title><link>http://testserver/</link><description>Latest research works with geographic metadata from OPTIMAP.</description><atom:link href="http://testserver/api/v1/feeds/optimap-global.rss" rel="self"/><language>en-us</language><lastBuildDate>Mon, 27 Oct 2025 21:43:33 +0000</lastBuildDate><atom:link href="http://testserver/api/v1/feeds/optimap-global.rss" rel="self" type="application/rss+xml"/><item><title>LineString Test</title><link>http://127.0.0.1:8000/work/10.1234/test-doi-3/</link><description>Publication with a linestring inside a collection.</description><pubDate>Sat, 20 May 2023 00:00:00 +0000</pubDate><guid>http://127.0.0.1:8000/work/10.1234/test-doi-3/</guid><georss:line>45.0 5.0 46.0 6.0 45.5 7.0</georss:line></item><item><title>Polygon Test</title><link>http://127.0.0.1:8000/work/10.1234/test-doi-2/</link><description>Publication with a polygon inside a collection.</description><pubDate>Mon, 15 May 2023 00:00:00 +0000</pubDate><guid>http://127.0.0.1:8000/work/10.1234/test-doi-2/</guid><georss:polygon>50.0 10.0 51.0 11.0 50.0 12.0 50.0 10.0</georss:polygon></item><item><title>Point Test</title><link>http://127.0.0.1:8000/work/10.1234/test-doi-1/</link><description>Publication with a single point inside a collection.</description><pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate><guid>http://127.0.0.1:8000/work/10.1234/test-doi-1/</guid><georss:point>41.8902 12.4924</georss:point></item></channel></rss>

tests/test_feed_landing_pages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
# Continents
2525
'africa': 15,
2626
'antarctica': 2,
27-
'asia': 20,
27+
'asia': 23,
2828
'australia': 6,
2929
'europe': 17,
3030
'north-america': 14,

works/feeds.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,15 +387,15 @@ def __init__(self, feed_type_variant="georss"):
387387
def title(self):
388388
"""Return feed title."""
389389
variant = self.feed_type_variant.upper()
390-
return f"OPTIMAP - Latest works ({variant})"
390+
return f"OPTIMAP - Latest works"
391391

392392
def link(self):
393393
"""Return feed link."""
394394
return "/"
395395

396396
def description(self):
397397
"""Return feed description."""
398-
return "Latest research works with geographic data from OPTIMAP."
398+
return "Latest research works with geographic metadata from OPTIMAP."
399399

400400
def items(self):
401401
"""Return feed items."""
@@ -432,7 +432,7 @@ def title(self, obj):
432432
"""Return feed title with region name."""
433433
variant = self.feed_type_variant.upper()
434434
region_type = obj.get_region_type_display()
435-
return f"OPTIMAP - {obj.name} ({region_type}) - Latest works ({variant})"
435+
return f"OPTIMAP - {obj.name} ({region_type}) - Latest works"
436436

437437
def link(self, obj):
438438
"""Return feed link."""
@@ -442,7 +442,7 @@ def description(self, obj):
442442
"""Return feed description with region name."""
443443
region_type = obj.get_region_type_display()
444444
return (
445-
f"Latest research works with geographic data from {obj.name} "
445+
f"Latest research works with geographic metadata from {obj.name} "
446446
f"({region_type}) on OPTIMAP."
447447
)
448448

works/templates/contribute.html

Lines changed: 142 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<div class="col-md-10 col-lg-8 py-5">
1010
<h1 class="py-2">Contribute Geolocation Data</h1>
1111

12-
<p class="lead">Help us add geographic data to scientific works!</p>
12+
<p class="lead">Help us add geographic metadata to scientific works!</p>
1313

1414
<p class="text-wrap text-break">The works listed below have been harvested from various scientific sources but do not have geolocation data yet. If you know the geographic location or area mentioned in any of these publications, you can help us improve our database.</p>
1515

@@ -19,12 +19,88 @@ <h1 class="py-2">Contribute Geolocation Data</h1>
1919
<strong>{{ total_count }}</strong> publication{{ total_count|pluralize }} need{{ total_count|pluralize:"s," }} geolocation data.
2020
</div>
2121

22+
<!-- Pagination controls (top) -->
23+
{% if page_obj %}
24+
<div class="pagination-controls mb-4">
25+
<div class="row align-items-center">
26+
<div class="col-md-6">
27+
<p class="mb-2">
28+
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} works
29+
</p>
30+
</div>
31+
<div class="col-md-6 text-md-right">
32+
<form method="get" class="form-inline justify-content-md-end">
33+
<label for="page-size" class="mr-2">Works per page:</label>
34+
<select name="size" id="page-size" class="form-control form-control-sm" onchange="this.form.submit()">
35+
{% for option in page_size_options %}
36+
<option value="{{ option }}" {% if option == page_size %}selected{% endif %}>{{ option }}</option>
37+
{% endfor %}
38+
</select>
39+
</form>
40+
</div>
41+
</div>
42+
43+
<!-- Pagination nav -->
44+
<nav aria-label="Works pagination" class="mt-3">
45+
<ul class="pagination justify-content-center">
46+
{% if page_obj.has_previous %}
47+
<li class="page-item">
48+
<a class="page-link" href="?page=1&size={{ page_size }}" aria-label="First">
49+
<span aria-hidden="true">&laquo;&laquo;</span>
50+
</a>
51+
</li>
52+
<li class="page-item">
53+
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&size={{ page_size }}" aria-label="Previous">
54+
<span aria-hidden="true">&laquo;</span>
55+
</a>
56+
</li>
57+
{% else %}
58+
<li class="page-item disabled">
59+
<span class="page-link">&laquo;&laquo;</span>
60+
</li>
61+
<li class="page-item disabled">
62+
<span class="page-link">&laquo;</span>
63+
</li>
64+
{% endif %}
65+
66+
{% for num in page_obj.paginator.page_range %}
67+
{% if page_obj.number == num %}
68+
<li class="page-item active"><span class="page-link">{{ num }} <span class="sr-only">(current)</span></span></li>
69+
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
70+
<li class="page-item"><a class="page-link" href="?page={{ num }}&size={{ page_size }}">{{ num }}</a></li>
71+
{% endif %}
72+
{% endfor %}
73+
74+
{% if page_obj.has_next %}
75+
<li class="page-item">
76+
<a class="page-link" href="?page={{ page_obj.next_page_number }}&size={{ page_size }}" aria-label="Next">
77+
<span aria-hidden="true">&raquo;</span>
78+
</a>
79+
</li>
80+
<li class="page-item">
81+
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}&size={{ page_size }}" aria-label="Last">
82+
<span aria-hidden="true">&raquo;&raquo;</span>
83+
</a>
84+
</li>
85+
{% else %}
86+
<li class="page-item disabled">
87+
<span class="page-link">&raquo;</span>
88+
</li>
89+
<li class="page-item disabled">
90+
<span class="page-link">&raquo;&raquo;</span>
91+
</li>
92+
{% endif %}
93+
</ul>
94+
</nav>
95+
</div>
96+
{% endif %}
97+
2298
<div class="publication-grid">
23-
{% for work in publications %}
99+
{% for work in works %}
24100
<div class="card locate-card">
25101
<div class="card-body">
26102
<h5 class="card-title">
27-
{% if publication.doi %}
103+
{% if work.doi %}
28104
<a href="https://doi.org/{{ work.doi }}" target="_blank" rel="noopener noreferrer">
29105
{{ work.title|truncatechars:120 }}
30106
<i class="fas fa-external-link-alt fa-xs"></i>
@@ -35,7 +111,7 @@ <h5 class="card-title">
35111
</h5>
36112

37113
<div class="abstract-area">
38-
{% if publication.abstract %}
114+
{% if work.abstract %}
39115
<p class="card-text text-muted small">
40116
{{ work.abstract|truncatechars:180 }}
41117
</p>
@@ -45,24 +121,24 @@ <h5 class="card-title">
45121

46122
<div class="card-footer">
47123
<small class="text-muted">
48-
{% if publication.publicationDate %}
124+
{% if work.publicationDate %}
49125
<div class="mb-1">Published: {{ work.publicationDate|date:"M d, Y" }}</div>
50126
{% endif %}
51-
{% if publication.source %}
127+
{% if work.source %}
52128
<div class="mb-1">Source: {{ work.source.name }}</div>
53129
{% endif %}
54-
{% if publication.doi %}
130+
{% if work.doi %}
55131
<div class="mb-1">DOI: <span class="doi-text">{{ work.doi }}</span></div>
56132
{% endif %}
57133
</small>
58134

59135
{% if request.user.is_authenticated %}
60-
{% if publication.doi %}
61-
<a href="{% url 'optimap:article-landing' publication.doi %}" class="btn btn-primary btn-sm">
136+
{% if work.doi %}
137+
<a href="{% url 'optimap:article-landing' work.doi %}" class="btn btn-primary btn-sm">
62138
<i class="fas fa-map-marked-alt"></i> Contribute metadata
63139
</a>
64140
{% else %}
65-
<a href="{% url 'optimap:publication-by-id' publication.id %}" class="btn btn-primary btn-sm">
141+
<a href="{% url 'optimap:publication-by-id' work.id %}" class="btn btn-primary btn-sm">
66142
<i class="fas fa-map-marked-alt"></i> Contribute metadata
67143
</a>
68144
{% endif %}
@@ -76,11 +152,61 @@ <h5 class="card-title">
76152
{% endfor %}
77153
</div>
78154

79-
{% if publications|length >= 100 %}
80-
<div class="alert alert-secondary mt-4" role="alert">
81-
<i class="fas fa-info-circle"></i>
82-
Showing first 100 of {{ publications|length }} works only. More publications without geolocation data are available, please make your contributions and then refresh this page. If you would like to contribute for a specific journal or field, please get in touch.
83-
</div>
155+
<!-- Pagination controls (bottom) -->
156+
{% if page_obj and page_obj.paginator.num_pages > 1 %}
157+
<div class="pagination-controls mt-4">
158+
<nav aria-label="Works pagination" class="mt-3">
159+
<ul class="pagination justify-content-center">
160+
{% if page_obj.has_previous %}
161+
<li class="page-item">
162+
<a class="page-link" href="?page=1&size={{ page_size }}" aria-label="First">
163+
<span aria-hidden="true">&laquo;&laquo;</span>
164+
</a>
165+
</li>
166+
<li class="page-item">
167+
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&size={{ page_size }}" aria-label="Previous">
168+
<span aria-hidden="true">&laquo;</span>
169+
</a>
170+
</li>
171+
{% else %}
172+
<li class="page-item disabled">
173+
<span class="page-link">&laquo;&laquo;</span>
174+
</li>
175+
<li class="page-item disabled">
176+
<span class="page-link">&laquo;</span>
177+
</li>
178+
{% endif %}
179+
180+
{% for num in page_obj.paginator.page_range %}
181+
{% if page_obj.number == num %}
182+
<li class="page-item active"><span class="page-link">{{ num }} <span class="sr-only">(current)</span></span></li>
183+
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
184+
<li class="page-item"><a class="page-link" href="?page={{ num }}&size={{ page_size }}">{{ num }}</a></li>
185+
{% endif %}
186+
{% endfor %}
187+
188+
{% if page_obj.has_next %}
189+
<li class="page-item">
190+
<a class="page-link" href="?page={{ page_obj.next_page_number }}&size={{ page_size }}" aria-label="Next">
191+
<span aria-hidden="true">&raquo;</span>
192+
</a>
193+
</li>
194+
<li class="page-item">
195+
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}&size={{ page_size }}" aria-label="Last">
196+
<span aria-hidden="true">&raquo;&raquo;</span>
197+
</a>
198+
</li>
199+
{% else %}
200+
<li class="page-item disabled">
201+
<span class="page-link">&raquo;</span>
202+
</li>
203+
<li class="page-item disabled">
204+
<span class="page-link">&raquo;&raquo;</span>
205+
</li>
206+
{% endif %}
207+
</ul>
208+
</nav>
209+
</div>
84210
{% endif %}
85211

86212
{% else %}
@@ -106,4 +232,4 @@ <h3>How to help</h3>
106232
</div>
107233
</div>
108234

109-
{% endblock content %}
235+
{% endblock %}

0 commit comments

Comments
 (0)