Skip to content

Commit c90ea63

Browse files
committed
feat(projects,pages): add find next page refactor progress #1191 #1193
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
1 parent 7562239 commit c90ea63

File tree

2 files changed

+72
-30
lines changed

2 files changed

+72
-30
lines changed

rdmo/projects/progress.py

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,47 @@ def compute_sets(values):
4747
return sets
4848

4949

50+
def compute_next_relevant_page(current_page, direction, catalog, resolved_conditions):
51+
"""
52+
Determine the next relevant page based on precomputed values and conditions.
53+
"""
54+
while True:
55+
# Determine the next page based on the specified direction
56+
next_page = (catalog.get_prev_page(current_page) if direction == 'prev'
57+
else catalog.get_next_page(current_page))
58+
59+
# If no further pages are available, return None
60+
if not next_page:
61+
return None
62+
63+
# Use compute_show_page with precomputed resolved_conditions to check if the next page meets conditions
64+
if compute_show_page(next_page, resolved_conditions):
65+
return next_page # Found the next relevant page
66+
67+
# Move to the next page in sequence if conditions are not met
68+
current_page = next_page
69+
70+
71+
def compute_show_page(page, conditions):
72+
"""Determine if a page should be shown based on resolved conditions."""
73+
# show only pages with resolved conditions, but show all pages without conditions
74+
pages_conditions = {page.id for page in page.conditions.all()}
75+
76+
if pages_conditions:
77+
# check if any valuesets for set_prefix = '' resolved
78+
# for non collection pages restrict further to set_index = 0
79+
return any(
80+
(
81+
(set_prefix == '') and
82+
((page.is_collection or set_index == 0) or (not page.is_collection and set_index))
83+
)
84+
for page_condition in pages_conditions
85+
for set_prefix, set_index in conditions[page_condition]
86+
)
87+
else:
88+
return True
89+
90+
5091
def compute_navigation(section, project, snapshot=None):
5192
# get all values for this project and snapshot
5293
values = project.values.filter(snapshot=snapshot).select_related('attribute', 'option')
@@ -74,19 +115,8 @@ def compute_navigation(section, project, snapshot=None):
74115
navigation_section['pages'] = []
75116

76117
for page in catalog_section.elements:
77-
pages_conditions = {page.id for page in page.conditions.all()}
78-
79-
# show only pages with resolved conditions, but show all pages without conditions
80-
if pages_conditions:
81-
# check if any valuesets for set_prefix = '' resolved
82-
# for non collection pages restrict further to set_index = 0
83-
show = any(
84-
(set_prefix == '') and (page.is_collection or set_index == 0)
85-
for page_condition in pages_conditions
86-
for set_prefix, set_index in conditions[page_condition]
87-
)
88-
else:
89-
show = True
118+
119+
show = compute_show_page(page, conditions)
90120

91121
# count the total number of questions, taking sets and conditions into account
92122
counts = count_questions(page, sets, conditions)

rdmo/projects/viewsets.py

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,14 @@
4242
HasProjectProgressObjectPermission,
4343
HasProjectsPermission,
4444
)
45-
from .progress import compute_navigation, compute_progress
45+
from .progress import (
46+
compute_navigation,
47+
compute_next_relevant_page,
48+
compute_progress,
49+
compute_sets,
50+
compute_show_page,
51+
resolve_conditions,
52+
)
4653
from .serializers.v1 import (
4754
IntegrationSerializer,
4855
InviteSerializer,
@@ -521,29 +528,34 @@ def dispatch(self, *args, **kwargs):
521528

522529
def retrieve(self, request, *args, **kwargs):
523530
page = self.get_object()
524-
conditions = page.conditions.select_related('source', 'target_option')
525-
531+
catalog = self.project.catalog
532+
# conditions = page.conditions.select_related('source', 'target_option')
526533
values = self.project.values.filter(snapshot=None).select_related('attribute', 'option')
527534

528-
if check_conditions(conditions, values):
535+
sets = compute_sets(values)
536+
resolved_conditions = resolve_conditions(catalog, values, sets)
537+
538+
# Check if the current page meets conditions
539+
if compute_show_page(page, resolved_conditions):
529540
serializer = self.get_serializer(page)
530541
return Response(serializer.data)
531542
else:
532-
if request.GET.get('back') == 'true':
533-
prev_page = self.project.catalog.get_prev_page(page)
534-
if prev_page is not None:
535-
url = reverse('v1-projects:project-page-detail',
536-
args=[self.project.id, prev_page.id]) + '?back=true'
537-
return HttpResponseRedirect(url, status=303)
538-
else:
539-
next_page = self.project.catalog.get_next_page(page)
540-
if next_page is not None:
541-
url = reverse('v1-projects:project-page-detail', args=[self.project.id, next_page.id])
542-
return HttpResponseRedirect(url, status=303)
543-
544-
# indicate end of catalog
543+
# Determine the direction of navigation (back or forward)
544+
direction = 'prev' if request.GET.get('back') == 'true' else 'next'
545+
546+
# Find the next relevant page with precomputed values and conditions
547+
next_page = compute_next_relevant_page(page, direction, catalog, resolved_conditions)
548+
549+
if next_page:
550+
url = reverse('v1-projects:project-page-detail', args=[self.project.id, next_page.id])
551+
if direction == 'prev':
552+
url += '?back=true'
553+
return HttpResponseRedirect(url, status=303)
554+
555+
# If no next relevant page is found, end of catalog
545556
return Response(status=204)
546557

558+
547559
@action(detail=False, url_path='continue', permission_classes=(HasModelPermission | HasProjectPagePermission, ))
548560
def get_continue(self, request, pk=None, parent_lookup_project=None):
549561
try:

0 commit comments

Comments
 (0)