Skip to content

Commit 6c183b3

Browse files
committed
Implement pagination in tab_inventory #3
Signed-off-by: tdruez <[email protected]>
1 parent b852e09 commit 6c183b3

File tree

2 files changed

+54
-39
lines changed

2 files changed

+54
-39
lines changed

dejacode/settings.py

+1
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ def gettext_noop(s):
371371

372372
# An integer specifying how many objects should be displayed per page.
373373
PAGINATE_BY = env.int("PAGINATE_BY", default=None)
374+
TAB_PAGINATE_BY = env.int("TAB_PAGINATE_BY", default=100)
374375

375376
ADMIN_FORMS_CONFIGURATION = env.dict("ADMIN_FORMS_CONFIGURATION", default={})
376377

product_portfolio/views.py

+53-39
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from operator import attrgetter
1515
from urllib.parse import unquote_plus
1616

17+
from django.conf import settings
1718
from django.contrib import messages
1819
from django.contrib.auth.decorators import login_required
1920
from django.contrib.auth.mixins import LoginRequiredMixin
@@ -64,6 +65,7 @@
6465
from dje.templatetags.dje_tags import urlize_target_blank
6566
from dje.utils import chunked
6667
from dje.utils import get_object_compare_diff
68+
from dje.utils import group_by_simple
6769
from dje.utils import is_uuid4
6870
from dje.views import DataspacedCreateView
6971
from dje.views import DataspacedDeleteView
@@ -418,63 +420,75 @@ def tab_hierarchy(self):
418420
return {"fields": [(None, context, None, template)]}
419421

420422
def tab_inventory(self):
421-
productcomponent_qs = self.filter_productcomponent.qs.order_by(
422-
"feature", "component", "name", "version"
423-
).group_by("feature")
424-
425-
productpackage_qs = self.filter_productpackage.qs.order_by(
426-
"feature", "package__type", "package__namespace", "package__name"
427-
).group_by("feature")
428-
429423
user = self.request.user
430424
dataspace = user.dataspace
431425

432-
scancodeio = ScanCodeIO(user)
433-
display_scan_features = all(
434-
[
435-
scancodeio.is_configured(),
436-
dataspace.enable_package_scanning,
437-
productpackage_qs,
438-
]
426+
productcomponent_qs = self.filter_productcomponent.qs.order_by(
427+
"feature",
428+
"component",
429+
"component__name",
430+
"component__version",
431+
"name",
432+
"version",
439433
)
440434

441-
if display_scan_features:
442-
self.display_scan_features = True
443-
injected_feature_grouped = self.inject_scan_data(
444-
scancodeio, productpackage_qs, dataspace.uuid
445-
)
446-
# Do not override the original data if ScanCode.io couldn't be reach
447-
if injected_feature_grouped:
448-
productpackage_qs = injected_feature_grouped
435+
productpackage_qs = self.filter_productpackage.qs.order_by(
436+
"feature",
437+
"package__type",
438+
"package__namespace",
439+
"package__name",
440+
"package__version",
441+
"package__filename",
442+
)
449443

450-
inventory_items = defaultdict(list)
451-
for relation_qs in [productcomponent_qs, productpackage_qs]:
452-
for feature, relation in relation_qs.items():
453-
inventory_items[feature].extend(relation)
444+
# 1. Combine components and packages into a single list of object
445+
all_inventory_items = list(productcomponent_qs) + list(productpackage_qs)
454446

455447
display_tab = any(
456448
[
457-
inventory_items,
449+
all_inventory_items,
458450
self.filter_productcomponent.is_active(),
459451
self.filter_productpackage.is_active(),
460452
]
461453
)
462-
463454
if not display_tab:
464455
return
465456

466-
count = sum((len(items) for items in inventory_items.values()))
467-
label = f'Inventory <span class="badge text-bg-primary">{count}</span>'
468-
inventory_items = dict(sorted(inventory_items.items()))
457+
# 2. Paginate the inventory list
458+
page_number = self.request.GET.get("inventory-page", 2)
459+
paginator = Paginator(all_inventory_items, settings.TAB_PAGINATE_BY)
460+
object_list = paginator.page(page_number).object_list
461+
462+
# 3. Group objects by features
463+
objects_by_feature = defaultdict(list)
464+
for feature, items in group_by_simple(object_list, "feature").items():
465+
objects_by_feature[feature].extend(items)
466+
467+
count = len(all_inventory_items)
468+
label = f'Inventory <span class="badge badge-primary">{count}</span>'
469469
tab_context = {
470-
"inventory_items": inventory_items,
470+
"inventory_items": dict(objects_by_feature.items()),
471471
}
472472

473+
# 4. Inject the Scan data when activated
474+
scancodeio = ScanCodeIO(user)
475+
display_scan_features = all(
476+
[
477+
scancodeio.is_configured(),
478+
dataspace.enable_package_scanning,
479+
productpackage_qs,
480+
]
481+
)
482+
if display_scan_features:
483+
self.display_scan_features = True
484+
self.inject_scan_data(scancodeio, objects_by_feature, dataspace.uuid)
485+
486+
# 5. Display the compliance alert based on license policies
473487
if self.show_licenses_policy:
474488
compliance_alerts = set(
475-
inventory_item.inventory_item_compliance_alert
476-
for inventory_group in inventory_items.values()
477-
for inventory_item in inventory_group
489+
alert
490+
for inventory_item in all_inventory_items
491+
for alert in inventory_item.compliance_alerts
478492
)
479493

480494
if "error" in compliance_alerts:
@@ -484,20 +498,19 @@ def tab_inventory(self):
484498
f' title="Compliance errors"></i> {label}'
485499
)
486500

501+
# 6. Add vulnerability data
487502
vulnerablecode = VulnerableCode(user)
488503
enable_vulnerabilities = all(
489504
[
490505
user.dataspace.enable_vulnerablecodedb_access,
491506
vulnerablecode.is_configured(),
492507
]
493508
)
494-
495509
if enable_vulnerabilities:
496510
# Re-use the inventory mapping to prevent duplicated queries
497511
packages = [
498512
inventory_item.package
499-
for inventory_group in inventory_items.values()
500-
for inventory_item in inventory_group
513+
for inventory_item in object_list
501514
if isinstance(inventory_item, ProductPackage)
502515
]
503516

@@ -516,6 +529,7 @@ def inject_scan_data(scancodeio, feature_grouped, dataspace_uuid):
516529
product_package.package.download_url
517530
for product_packages in feature_grouped.values()
518531
for product_package in product_packages
532+
if isinstance(product_package, ProductPackage)
519533
]
520534

521535
# WARNING: Do not trigger a Request for an empty list of download_urls

0 commit comments

Comments
 (0)