Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/wp 312 view users pagination #229

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions apcd-cms/src/apps/components/paginator/api_pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from django.utils.functional import cached_property
from django.core.paginator import Paginator, EmptyPage
import logging
import collections.abc

logger = logging.getLogger(__name__)


class APIPagination(Paginator):
def __init__(self, table_rows, entries_per_page, total_count):
"""

:param table_rows: paginator object_list
:param entries_per_page: entries per page (paginator - per_page)
:param total_count: Total count of record found in db -recieved from APCD API
"""
self.total_count = total_count
super(APIPagination, self).__init__(table_rows, entries_per_page)

@cached_property
def count(self):
return self.total_count

def page(self, number):
"""Return a Page object for the given 1-based page number."""
number = self.validate_number(number)
bottom = (number - 1) * self.per_page
top = bottom + self.per_page
if top + self.orphans >= self.count:
top = self.count
# return self._get_page(self.object_list[bottom:top], number, self)
return self._get_page(self.object_list, number, self)

def _get_page(self, *args, **kwargs):
"""
Return an instance of a single page.

This hook can be used by subclasses to use an alternative to the
standard :cls:`Page` object.
"""
return Page(*args, **kwargs)


class Page(collections.abc.Sequence):
def __init__(self, object_list, number, paginator):
self.object_list = object_list
self.number = number
self.paginator = paginator

def __repr__(self):
return "<Page %s of %s>" % (self.number, self.paginator.num_pages)

def __len__(self):
return len(self.object_list)

def __getitem__(self, index):
if not isinstance(index, (int, slice)):
raise TypeError(
"Page indices must be integers or slices, not %s."
% type(index).__name__
)
# The object_list is converted to a list so that if it was a QuerySet
# it won't be a database hit per __getitem__.
if not isinstance(self.object_list, list):
self.object_list = list(self.object_list)
return self.object_list[index]

def has_next(self):
return self.number < self.paginator.num_pages

def has_previous(self):
return self.number > 1

def has_other_pages(self):
return self.has_previous() or self.has_next()

def next_page_number(self):
return self.paginator.validate_number(self.number + 1)

def previous_page_number(self):
return self.paginator.validate_number(self.number - 1)

def start_index(self):
"""
Return the 1-based index of the first object on this page,
relative to total objects in the paginator.
"""
# Special case, return zero if no items.
if self.paginator.count == 0:
return 0
return (self.paginator.per_page * (self.number - 1)) + 1

def end_index(self):
"""
Return the 1-based index of the last object on this page,
relative to total objects found (hits).
"""
# Special case for the last page because there can be orphans.
if self.number == self.paginator.num_pages:
return self.paginator.count
return self.number * self.paginator.per_page
49 changes: 49 additions & 0 deletions apcd-cms/src/apps/components/paginator/custom_api_paginator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from django.core.paginator import Paginator, EmptyPage
from apps.components.paginator.api_pagination import APIPagination
import logging

logger = logging.getLogger(__name__)


def paginator(request, api_content, entries_per_page=50):
try:
page_num = int(request.GET.get('page'))
except:
page_num = 1

"""
First entry: Content for page
2nd Entry: Count of items per page
3rd entry: Total records matching criteria
"""
p = APIPagination(api_content['items'], entries_per_page, api_content['total_count'])


try:
page = p.page(page_num)
except EmptyPage:
page = p.page(1)

# print(f"Page info is: {page.object_list}")

elided_pages = []
on_ends = 1
current_page_buffer = 2
if page.paginator.num_pages <= (current_page_buffer + on_ends) * 2:
return {'page': page, 'elided_pages': page.paginator.page_range}

if page_num > (1 + current_page_buffer + on_ends) + 1:
elided_pages.extend(range(1, on_ends + 1))
elided_pages.append('...')
elided_pages.extend(range(page_num - current_page_buffer, page_num + 1))
else:
elided_pages.extend(range(1, page_num + 1))

if page_num < (page.paginator.num_pages - current_page_buffer - on_ends) - 1:
elided_pages.extend(range(page_num + 1, page_num + current_page_buffer + 1))
elided_pages.append('...')
elided_pages.extend(range(page.paginator.num_pages - on_ends + 1, page.paginator.num_pages + 1))
else:
elided_pages.extend(range(page_num + 1, page.paginator.num_pages + 1))

return {'page': page, 'elided_pages': elided_pages}
51 changes: 51 additions & 0 deletions apcd-cms/src/apps/utils/apcd_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,61 @@
from datetime import datetime
import re
import logging
import requests
import json

logger = logging.getLogger(__name__)

APCD_DB = settings.APCD_DATABASE
API_URL = settings.APCD_API_URL


def get_api_users(page: int = 1, per_page: int = 50, status: str = None, org: str = None):
org = None if org is None or status == "All" else org

payload = {
'page': page,
'per_page': per_page,
'status': status,
'org': org,
}

apcd_api_res = requests.get(f'{API_URL}/users/paged_users', params=payload)
print(f"API Request: {apcd_api_res.url}")
if apcd_api_res.status_code != 200:
response = apcd_api_res.text
logger.error(f"API issue: {response}")
return {'pgerror': apcd_api_res.text}

results = apcd_api_res.json()
return results


def update_api_users(user_id: int, payload: dict):

headers = {'content-type': 'application/json'}
apcd_api_res = requests.put(url=f'{API_URL}/users/{user_id}', headers=headers, data=json.dumps(payload))
print(f"API Request: {apcd_api_res.url}")
if apcd_api_res.status_code != 200:
response = apcd_api_res.text
logger.error(f"API issue: {response}")
return {'pgerror': apcd_api_res.text}

results = apcd_api_res.json()
return results


def get_api_users_org_list():

apcd_api_res = requests.get(url=f'{API_URL}/users/orgs')
print(f"API Request: {apcd_api_res.url}")
if apcd_api_res.status_code != 200:
response = apcd_api_res.text
logger.error(f"API issue: {response}")
return {'pgerror': apcd_api_res.text}

results = apcd_api_res.json()
return results


def get_users():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ <h4 class="modal-header">Edit Selected User</h4>
{% csrf_token %}
<div class="field-wrapper textinput required disabled">
<input type="hidden" name="user_id" id="user_id" value="{{r.user_id}}">
<input type="hidden" name="user_number" id="user_number" value="{{r.user_number}}">
</div>
<div class="o-grid o-grid--col-auto-count">
<div class="field-wrapper text required">
Expand Down Expand Up @@ -48,7 +49,7 @@ <h4 class="modal-header">Edit Selected User</h4>
</label>
<select name='status' class="choicefield" id='status'>
{% for s in status %}
<option class="dropdown-text" value="{{ s }}" {% if s == r.status %}selected{% endif %}>{{ s }}</option>
<option class="dropdown-text" value="{{ s }}" {% if s == r.active %}selected{% endif %}>{{ s }}</option>
{% endfor %}
</select>
</div>
Expand Down Expand Up @@ -99,8 +100,8 @@ <h4 class="modal-header">Edit Selected User</h4>
<dd class="c-data-list__value">{{r.org_name}}</dd>
<dt class="c-data-list__key">Role</dt>
<dd class="c-data-list__value">{{r.role_name}}</dd>
<dt class="c-data-list__key">Status</dt>
<dd class="c-data-list__value">{{r.status}}</dd>
<dt class="c-data-list__key">Active</dt>
<dd class="c-data-list__value">{{r.active}}</dd>
<dt class="c-data-list__key">Created</dt>
<dd class="c-data-list__value">{{r.created_at}}</dd>
<dt class="c-data-list__key">Updated</dt>
Expand Down
4 changes: 2 additions & 2 deletions apcd-cms/src/apps/view_users/templates/view_user_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ <h4 class="modal-title">Details for User: {{r.user_name}} ({{r.user_id}})</h4>
<dd class="c-data-list__value">{{r.org_name}}</dd>
<dt class="c-data-list__key">Role</dt>
<dd class="c-data-list__value">{{r.role_name}}</dd>
<dt class="c-data-list__key">Status</dt>
<dd class="c-data-list__value">{{r.status}}</dd>
<dt class="c-data-list__key">Active</dt>
<dd class="c-data-list__value">{{r.active}}</dd>
<dt class="c-data-list__key">Created</dt>
<dd class="c-data-list__value">{{r.created_at}}</dd>
<dt class="c-data-list__key">Updated</dt>
Expand Down
2 changes: 1 addition & 1 deletion apcd-cms/src/apps/view_users/templates/view_users.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ <h1>View Users</h1>
<td>{{r.user_name}}</td>
<td>{{r.org_name}}</td>
<td>{{r.role_name}}</td>
<td>{{r.status}}</td>
<td>{{r.active}}</td>
<td>{{r.user_number}}</td>
<td class="modal-cell">
{% include "view_user_modal.html" %}
Expand Down
Loading