Skip to content

Commit

Permalink
feat(projects, pages): refactor compute show page and next page
Browse files Browse the repository at this point in the history
Signed-off-by: David Wallace <[email protected]>
  • Loading branch information
MyPyDavid committed Nov 14, 2024
1 parent 9756d2c commit 3e06cd8
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 42 deletions.
56 changes: 43 additions & 13 deletions rdmo/projects/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,47 @@ def compute_sets(values):
return sets


def compute_next_relevant_page(current_page, direction, catalog, resolved_conditions):
"""
Determine the next relevant page based on precomputed values and conditions.
"""
while True:
# 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


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) or (not page.is_collection and set_index))
)
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 +115,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
46 changes: 17 additions & 29 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,17 +528,23 @@ 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
# conditions = page.conditions.select_related('source', 'target_option')
values = self.project.values.filter(snapshot=None).select_related('attribute', 'option')

sets = compute_sets(values)
resolved_conditions = resolve_conditions(catalog, values, sets)

# Check if the current page meets conditions
if check_conditions(conditions, values):
if compute_show_page(page, resolved_conditions):
serializer = self.get_serializer(page)
return Response(serializer.data)
else:
# Determine the direction of navigation (back or forward)
direction = 'prev' if request.GET.get('back') == 'true' else 'next'
next_page = self._find_next_relevant_page(page, direction)

# Find the next relevant page with precomputed values and conditions
next_page = compute_next_relevant_page(page, direction, catalog, resolved_conditions)

if next_page:
url = reverse('v1-projects:project-page-detail', args=[self.project.id, next_page.id])
Expand All @@ -542,31 +555,6 @@ def retrieve(self, request, *args, **kwargs):
# If no next relevant page is found, end of catalog
return Response(status=204)

def _find_next_relevant_page(self, page, direction):
"""
Helper method to find the next page that meets conditions.
:param page: current page object
:param direction: 'next' or 'prev' direction for navigation
:return: next relevant page or None if no further page meets conditions
"""
while True:
if direction == 'prev':
next_page = self.project.catalog.get_prev_page(page)
else:
next_page = self.project.catalog.get_next_page(page)

# Break the loop if no more pages are available
if not next_page:
return None

# Check if the next page meets conditions
conditions = next_page.conditions.select_related('source', 'target_option')
values = self.project.values.filter(snapshot=None).select_related('attribute', 'option')
if check_conditions(conditions, values):
return next_page # Found the final target page

# Move to the next page in the loop
page = next_page

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

0 comments on commit 3e06cd8

Please sign in to comment.