diff --git a/scanpipe/models.py b/scanpipe/models.py
index 0ecd8e6392..a4c19020d4 100644
--- a/scanpipe/models.py
+++ b/scanpipe/models.py
@@ -46,6 +46,7 @@
from django.db import transaction
from django.db.models import Case
from django.db.models import Count
+from django.db.models import Exists
from django.db.models import IntegerField
from django.db.models import OuterRef
from django.db.models import Prefetch
@@ -2425,6 +2426,17 @@ def macho_binaries(self):
def executable_binaries(self):
return self.union(self.win_exes(), self.macho_binaries(), self.elfs())
+ def with_has_children(self):
+ """
+ Annotate the QuerySet with has_children field based on whether
+ each resource has any children (subdirectories/files).
+ """
+ children_qs = CodebaseResource.objects.filter(
+ parent_path=OuterRef("path"),
+ )
+
+ return self.annotate(has_children=Exists(children_qs))
+
class ScanFieldsModelMixin(models.Model):
"""Fields returned by the ScanCode-toolkit scans."""
diff --git a/scanpipe/templates/scanpipe/panels/codebase_tree_panel.html b/scanpipe/templates/scanpipe/panels/codebase_tree_panel.html
new file mode 100644
index 0000000000..02becc016f
--- /dev/null
+++ b/scanpipe/templates/scanpipe/panels/codebase_tree_panel.html
@@ -0,0 +1,29 @@
+