Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add Dependency model and view #138 #147

Merged
merged 48 commits into from
Aug 5, 2024
Merged
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
5b7b5cf
Add prototype for Dependency model and view #138
tdruez Jul 5, 2024
e9b7fde
Merge branch 'main' into 138-dependencies
tdruez Jul 15, 2024
108db2d
Remove code duplication to generate SCIO API URLs #138
tdruez Jul 15, 2024
2b35f62
Refactor fetch_results to remove duplication #138
tdruez Jul 15, 2024
872c144
Add admin for the new ProductDependency model #138
tdruez Jul 15, 2024
db04c6d
Add API endpoint for the ProductDependency model #138
tdruez Jul 16, 2024
17b8f6b
Add filters in the Dependencies tab #138
tdruez Jul 16, 2024
c75204e
Refine the rendering of license_expression #138
tdruez Jul 16, 2024
760d92b
Merge branch 'main' into 138-dependencies
tdruez Jul 17, 2024
6522945
Merge branch 'main' into 138-dependencies
tdruez Jul 17, 2024
ce9311c
Consolidate migration files #138
tdruez Jul 17, 2024
565ad1b
Fix couple of failing tests #138
tdruez Jul 17, 2024
144797e
Refine the import_dependency method #138
tdruez Jul 17, 2024
bc6476a
Refactor the whole results system #138
tdruez Jul 17, 2024
6b22815
Proper pagination for Dependencies tab #138
tdruez Jul 17, 2024
a684f70
Refine the Import tab table input column #138
tdruez Jul 17, 2024
984ecdd
Fix the results count #138
tdruez Jul 17, 2024
a8b79f9
Use htmx to load only the tab content on page change #138
tdruez Jul 17, 2024
38e4c8c
Display the dependency Package URL in the tab table #138
tdruez Jul 17, 2024
6d0bca9
Fix template #138
tdruez Jul 17, 2024
ce7faf7
Add inline help in the headers of the Dependencies tab #138
tdruez Jul 18, 2024
67cb308
Add filter by package relationships availability #138
tdruez Jul 18, 2024
72c9c20
Add link from the Inventory tab to the filtered Dependencies #138
tdruez Jul 18, 2024
341e153
Add new Dependency model in reporting #138
tdruez Jul 18, 2024
b7076bd
Display the active filters breadcrumbs in dependencies tab #138
tdruez Jul 24, 2024
0f0dafd
Reorganise the dependencies tab layout #138
tdruez Jul 24, 2024
c1530b9
Merge branch 'main' into 138-dependencies
tdruez Jul 25, 2024
eb07b7f
Refine the Dependencies tab UI #138
tdruez Jul 25, 2024
6d3f4ce
Add full purl search for the Dependencies tab UI #138
tdruez Jul 25, 2024
0d5592c
Add some navigation counts in Dependencies UI #138
tdruez Jul 25, 2024
32ebfc5
Refine the global search UI #138
tdruez Jul 26, 2024
e6c4248
Move the declared_dependency help text to the view #138
tdruez Jul 26, 2024
f70c48a
Round of queryset optimizations #138
tdruez Jul 26, 2024
93724bc
Add declared_dependency field on ProductDependency model #138
tdruez Aug 2, 2024
6cee948
Remove the restrictive pipeline name validation in import #138
tdruez Aug 2, 2024
dbc3a54
WIP on the product scoping for dependency count #138
tdruez Aug 2, 2024
e3d4376
Refine the QuerySet and count Product scoping #138
tdruez Aug 2, 2024
6b4d4ca
Turn off the license_expression rendering #138
tdruez Aug 2, 2024
dc4ca0a
Improve unit tests #138
tdruez Aug 2, 2024
692cfef
Fix failing unit tests #138
tdruez Aug 2, 2024
4d6ca9c
Fix remaining failing unit tests #138
tdruez Aug 2, 2024
a6ee9f6
Consolidate migration files #138
tdruez Aug 2, 2024
4256988
Add unit tests #138
tdruez Aug 2, 2024
6c1cd66
Make sure a Package dependency cannot resolve to itself #138
tdruez Aug 2, 2024
e5820e2
Use assertMaxQueries in place of exact query number #138
tdruez Aug 2, 2024
52d9b41
Add unit test #138
tdruez Aug 5, 2024
2803fcc
Improve the global search UI #138
tdruez Aug 5, 2024
03f4601
Add changelog entry #138
tdruez Aug 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Round of queryset optimizations #138
Signed-off-by: tdruez <tdruez@nexb.com>
tdruez committed Jul 26, 2024
commit f70c48ae043d34238532a23f5ed932b699cd948d
13 changes: 13 additions & 0 deletions component_catalog/models.py
Original file line number Diff line number Diff line change
@@ -1633,6 +1633,19 @@ def annotate_sortable_identifier(self):
sortable_identifier=Concat(*PACKAGE_URL_FIELDS, "filename", output_field=CharField())
)

def only_rendering_fields(self):
"""
Minimum requirements to render a Package element in the UI.
"""
return self.only(
"uuid",
*PACKAGE_URL_FIELDS,
"filename",
"license_expression",
"dataspace__name",
"dataspace__show_usage_policy_in_user_views",
)


class Package(
ExternalReferenceMixin,
7 changes: 5 additions & 2 deletions license_library/models.py
Original file line number Diff line number Diff line change
@@ -472,8 +472,11 @@ def for_expression(self, license_keys=None):
"short_name",
"spdx_license_key",
"is_exception",
"usage_policy",
"dataspace",
"usage_policy__label",
"usage_policy__icon",
"usage_policy__color_code",
"dataspace__name",
"dataspace__show_usage_policy_in_user_views",
).select_related("dataspace", "usage_policy")

if license_keys:
4 changes: 4 additions & 0 deletions product_portfolio/models.py
Original file line number Diff line number Diff line change
@@ -547,6 +547,10 @@ def product_secured(self, user=None, perms="view_product"):
product_qs = Product.objects.get_queryset(user, perms)
return self.filter(product__in=product_qs)

def product(self, product):
"""Filter based on the provided ``product`` object."""
return self.filter(product=product)


class ProductComponentQuerySet(ProductSecuredQuerySet):
def catalogs(self):
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
<div class="h6 mt-2 mb-0 smaller">
{% if page_obj.paginator.count != total_count %}
{{ page_obj.paginator.count|intcomma }} of
<a href="#" hx-get="{{ request.path }}?all=true#inventory" hx-target="{{ tab_id_html }}">
<a href="#" hx-get="{{ request.path }}?all=true#dependencies" hx-target="{{ tab_id_html }}">
{{ total_count }} results
</a>
{% else %}
@@ -120,7 +120,7 @@
</a>
{% endif %}
</strong>
<div class="license-expression">
<div>
{{ dependency.resolved_to_package.license_expression_html|default_if_none:"" }}
</div>
{% else %}
@@ -156,7 +156,9 @@
<td colspan="10">
No results.
{% if filter_dependency.is_active %}
<a href="?all=true#dependencies">Clear search and filters</a>
<a href="#" hx-get="{{ request.path }}?all=true#dependencies" hx-target="{{ tab_id_html }}">
Clear search and filters
</a>
{% endif %}
</td>
</tr>
37 changes: 29 additions & 8 deletions product_portfolio/views.py
Original file line number Diff line number Diff line change
@@ -391,8 +391,10 @@ def tab_notice(self):

def tab_hierarchy(self):
template = "product_portfolio/tabs/tab_hierarchy.html"
product = self.object

productcomponent_qs = (
self.object.productcomponents.select_related(
product.productcomponents.select_related(
"component",
)
.prefetch_related(
@@ -410,11 +412,12 @@ def tab_hierarchy(self):
)

declared_dependencies_prefetch = models.Prefetch(
"package__declared_dependencies", ProductDependency.objects.all()
"package__declared_dependencies",
ProductDependency.objects.product(product)
)

productpackage_qs = (
self.object.productpackages.select_related(
product.productpackages.select_related(
"package",
)
.prefetch_related(
@@ -648,7 +651,8 @@ def get_context_data(self, **kwargs):
"licenses", License.objects.select_related("usage_policy")
)
declared_dependencies_prefetch = models.Prefetch(
"package__declared_dependencies", ProductDependency.objects.all()
"package__declared_dependencies",
ProductDependency.objects.product(self.object)
)

productpackage_qs = (
@@ -964,9 +968,16 @@ class ProductTabDependenciesView(
def get_context_data(self, **kwargs):
context_data = super().get_context_data(**kwargs)

dependency_qs = self.object.dependencies.select_related(
"for_package__dataspace",
"resolved_to_package__dataspace",
dependency_qs = (
self.object.dependencies
.prefetch_related(
models.Prefetch(
"for_package", Package.objects.only_rendering_fields()
),
models.Prefetch(
"resolved_to_package", Package.objects.only_rendering_fields()
)
)
)

filter_dependency = DependencyFilterSet(
@@ -977,7 +988,17 @@ def get_context_data(self, **kwargs):
)

# Annotate the filtered queryset with the count of declared_dependencies
filtered_and_annotated_qs = filter_dependency.qs.with_resolved_to_dependencies_count()
filtered_and_annotated_qs = (
filter_dependency.qs
# TODO: This is not scoped by product
.with_resolved_to_dependencies_count()
.order_by(
"for_package__type",
"for_package__namespace",
"for_package__name",
"for_package__version",
)
)

paginator = Paginator(filtered_and_annotated_qs, self.paginate_by)
page_number = self.request.GET.get(self.query_dict_page_param)