Skip to content

Commit

Permalink
feat(projects): add method to find next relevant page #1191
Browse files Browse the repository at this point in the history
Signed-off-by: David Wallace <[email protected]>
  • Loading branch information
MyPyDavid committed Nov 27, 2024
1 parent cde2c42 commit 6f8244e
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 30 deletions.
57 changes: 44 additions & 13 deletions rdmo/projects/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,48 @@ def compute_sets(values):
return sets


def compute_next_relevant_page(current_page, direction, catalog, resolved_conditions):
# compute the next relevant page based on resolved conditions.
max_iterations = len(catalog.pages)
iterations = 0

while iterations < max_iterations:
iterations += 1

# Determine the next page based on the specified direction
next_page = (catalog.get_prev_page(current_page) if direction == 'prev'
else catalog.get_next_page(current_page))

# If no further pages are available, return None
if not next_page:
return None

# Use compute_show_page with precomputed resolved_conditions to check if the next page meets conditions
if compute_show_page(next_page, resolved_conditions):
return next_page # Found the next relevant page

# Move to the next page in sequence if conditions are not met
current_page = next_page
return None

def compute_show_page(page, conditions):
"""Determine if a page should be shown based on resolved conditions."""
# show only pages with resolved conditions, but show all pages without conditions
pages_conditions = {page.id for page in page.conditions.all()}

if pages_conditions:
# check if any valuesets for set_prefix = '' resolved
# for non collection pages restrict further to set_index = 0

return any(
(set_prefix == '') and (page.is_collection or set_index == 0)
for page_condition in pages_conditions
for set_prefix, set_index in conditions[page_condition]
)
else:
return True


def compute_navigation(section, project, snapshot=None):
# get all values for this project and snapshot
values = project.values.filter(snapshot=snapshot).select_related('attribute', 'option')
Expand Down Expand Up @@ -74,19 +116,8 @@ def compute_navigation(section, project, snapshot=None):
navigation_section['pages'] = []

for page in catalog_section.elements:
pages_conditions = {page.id for page in page.conditions.all()}

# show only pages with resolved conditions, but show all pages without conditions
if pages_conditions:
# check if any valuesets for set_prefix = '' resolved
# for non collection pages restrict further to set_index = 0
show = any(
(set_prefix == '') and (page.is_collection or set_index == 0)
for page_condition in pages_conditions
for set_prefix, set_index in conditions[page_condition]
)
else:
show = True

show = compute_show_page(page, conditions)

# count the total number of questions, taking sets and conditions into account
counts = count_questions(page, sets, conditions)
Expand Down
45 changes: 28 additions & 17 deletions rdmo/projects/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@
HasProjectProgressObjectPermission,
HasProjectsPermission,
)
from .progress import compute_navigation, compute_progress
from .progress import (
compute_navigation,
compute_next_relevant_page,
compute_progress,
compute_sets,
compute_show_page,
resolve_conditions,
)
from .serializers.v1 import (
IntegrationSerializer,
InviteSerializer,
Expand Down Expand Up @@ -521,29 +528,33 @@ def dispatch(self, *args, **kwargs):

def retrieve(self, request, *args, **kwargs):
page = self.get_object()
conditions = page.conditions.select_related('source', 'target_option')

catalog = self.project.catalog
values = self.project.values.filter(snapshot=None).select_related('attribute', 'option')

if check_conditions(conditions, values):
sets = compute_sets(values)
resolved_conditions = resolve_conditions(catalog, values, sets)

# check if the current page meets conditions
if compute_show_page(page, resolved_conditions):
serializer = self.get_serializer(page)
return Response(serializer.data)
else:
if request.GET.get('back') == 'true':
prev_page = self.project.catalog.get_prev_page(page)
if prev_page is not None:
url = reverse('v1-projects:project-page-detail',
args=[self.project.id, prev_page.id]) + '?back=true'
return HttpResponseRedirect(url, status=303)
else:
next_page = self.project.catalog.get_next_page(page)
if next_page is not None:
url = reverse('v1-projects:project-page-detail', args=[self.project.id, next_page.id])
return HttpResponseRedirect(url, status=303)

# indicate end of catalog
# determine the direction of navigation (previous or next)
direction = 'prev' if request.GET.get('back') == 'true' else 'next'

# find the next relevant page with from pages and resolved conditions
next_page = compute_next_relevant_page(page, direction, catalog, resolved_conditions)

if next_page is not None:
url = reverse('v1-projects:project-page-detail', args=[self.project.id, next_page.id])
if direction == 'prev':
url += '?back=true'
return HttpResponseRedirect(url, status=303)

# end of catalog, if no next relevant page is found
return Response(status=204)


@action(detail=False, url_path='continue', permission_classes=(HasModelPermission | HasProjectPagePermission, ))
def get_continue(self, request, pk=None, parent_lookup_project=None):
try:
Expand Down

0 comments on commit 6f8244e

Please sign in to comment.