Skip to content

Commit

Permalink
Use server-side paging in aips page. (#209)
Browse files Browse the repository at this point in the history
To avoid slow page responses when there are a large amount of AIPs use
server-side paging to limit the number of AIP HTML sent to the browser.
  • Loading branch information
mcantelon committed Sep 29, 2023
1 parent 40b01a3 commit 7765c14
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 21 deletions.
10 changes: 10 additions & 0 deletions AIPscan/Reporter/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,13 @@ def get_premis_xml_lines(file_object):
premis_xml_lines = file_object.premis_object.split("\n")

return premis_xml_lines


def calculate_paging_window(page, pagination):
first_item = ((page - 1) * pagination.per_page) + 1
last_item = page * pagination.per_page

if last_item > pagination.total:
last_item = pagination.total

return first_item, last_item
53 changes: 37 additions & 16 deletions AIPscan/Reporter/templates/aips.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

{% block content %}

<div class="alert alert-header"><strong>AIPs ({{ aips|length }})</strong></div>
<div class="alert alert-header"><strong>AIPs ({{ paging.items|length }})</strong></div>

{% if storage_services %}

Expand Down Expand Up @@ -42,9 +42,9 @@
</div>
</div>

{% if aips %}
{% if paging.items %}

<table id="aiptable" class="table table-striped table-bordered">
<table id="aipstable" class="table table-striped table-bordered">
<thead>
<tr>
<th><strong>Transfer name</strong></th>
Expand All @@ -54,19 +54,17 @@
<th><strong>Preservation copies</strong></th>
<th><strong>Action</strong></th>
</tr>
</thead>
{% if aips %}
{% for aip in aips %}
<tr>
<td>{{ aip.transfer_name }}</td>
<td>{{ aip.uuid }}</td>
<td>{{ aip.create_date }}</td>
<td>{{ aip.original_file_count }}</td>
<td>{{ aip.preservation_file_count }}</td>
<td><a href='{{ url_for("reporter.view_aip", aip_id = aip.id) }}'><button type="button" class="btn btn-info">View</button></a></td>
</tr>
{% endfor %}
{% endif %}

{% for aip in paging.items %}
<tr>
<td>{{ aip.transfer_name }}</td>
<td>{{ aip.uuid }}</td>
<td>{{ aip.create_date }}</td>
<td>{{ aip.original_file_count }}</td>
<td>{{ aip.preservation_file_count }}</td>
<td><a href='{{ url_for("reporter.view_aip", aip_id = aip.id) }}'><button type="button" class="btn btn-info">View</button></a></td>
</tr>
{% endfor %}
</table>

{% else %}
Expand All @@ -85,6 +83,29 @@

{% endif %}

{% if paging.total %}

<div class="dataTables_wrapper">
<div class="row">
<div class="col-sm-12 col-md-5">
<div class="dataTables_info" id="aiptable_info" role="status" aria-live="polite">Showing {{ first_item }} to {{ last_item }} of {{ paging.total }} entries</div>
</div>
<div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_full_numbers" id="aiptable_paginate">
<ul class="pagination">
<li class="paginate_button page-item first {% if paging.page == 1 %}disabled{% endif %}"><a href="{{ url_for('reporter.view_aips') }}?page=1" class="page-link">First</a></li>
<li class="paginate_button page-item previous {% if paging.prev_num is none %}disabled{% endif %}"><a href="{{ url_for('reporter.view_aips') }}?page={{ paging.prev_num }}" class="page-link">Previous</a></li>
<li class="paginate_button page-item active"><a href="#" class="page-link">{{ paging.page }}</a></li>
<li class="paginate_button page-item next {% if paging.next_num is none %}disabled{% endif %}"><a href="{{ url_for('reporter.view_aips') }}?page={{ paging.next_num }}" class="page-link">Next</a></li>
<li class="paginate_button page-item last {% if paging.page == paging.pages %}disabled{% endif %}"><a href="{{ url_for('reporter.view_aips') }}?page={{ paging.pages }}" class="page-link">Last</a></li>
</ul>
</div>
</div>
</div>
</div>

{% endif %}

<script>
$(document).ready(function(){
var storageServiceId = $('#ss').val();
Expand Down
27 changes: 27 additions & 0 deletions AIPscan/Reporter/tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,30 @@ def test_get_premis_xml_lines():
lines = helpers.get_premis_xml_lines(file_)

assert len(lines) == 2


def test_calculate_paging_window():
class MockPagination(object):
pass

pagination = MockPagination()
pagination.per_page = 5
pagination.total = 17

# Test paging window at start of results
first_item, last_item = helpers.calculate_paging_window(1, pagination)

assert first_item == 1
assert last_item == 5

# Test paging window on an arbitrary page of results
first_item, last_item = helpers.calculate_paging_window(3, pagination)

assert first_item == 11
assert last_item == 15

# Test paging window with last item being set to the total of items
first_item, last_item = helpers.calculate_paging_window(4, pagination)

assert first_item == 16
assert last_item == 17
19 changes: 14 additions & 5 deletions AIPscan/Reporter/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
request_params,
sort_puids,
)
from AIPscan.Reporter.helpers import get_premis_xml_lines
from AIPscan.Reporter.helpers import calculate_paging_window, get_premis_xml_lines


def _get_storage_service(storage_service_id):
Expand Down Expand Up @@ -85,10 +85,17 @@ def view_aips():
except Exception as e:
print(e)

aips = AIP.query.filter_by(storage_service_id=storage_service.id)
page = int(request.args.get("page", default="1"))
per_page = 5

Check warning on line 89 in AIPscan/Reporter/views.py

View check run for this annotation

Codecov / codecov/patch

AIPscan/Reporter/views.py#L88-L89

Added lines #L88 - L89 were not covered by tests

paging = AIP.query.paginate(page=page, per_page=per_page, error_out=False)

Check warning on line 91 in AIPscan/Reporter/views.py

View check run for this annotation

Codecov / codecov/patch

AIPscan/Reporter/views.py#L91

Added line #L91 was not covered by tests

if storage_location:
aips = aips.filter_by(storage_location_id=storage_location_id)
aips = aips.all()
paging = AIP.query.filter_by(

Check warning on line 94 in AIPscan/Reporter/views.py

View check run for this annotation

Codecov / codecov/patch

AIPscan/Reporter/views.py#L94

Added line #L94 was not covered by tests
storage_location_id=storage_location_id
).paginate(page=page, per_page=per_page, error_out=False)

first_item, last_item = calculate_paging_window(page, paging)

Check warning on line 98 in AIPscan/Reporter/views.py

View check run for this annotation

Codecov / codecov/patch

AIPscan/Reporter/views.py#L98

Added line #L98 was not covered by tests

return render_template(
"aips.html",
Expand All @@ -98,7 +105,9 @@ def view_aips():
storage_service.storage_locations
),
storage_location=storage_location,
aips=aips,
paging=paging,
first_item=first_item,
last_item=last_item,
)


Expand Down

0 comments on commit 7765c14

Please sign in to comment.