Skip to content

Commit f873c76

Browse files
committed
Merge branch 'main' into 235-altcha
2 parents 5376849 + 30aa2eb commit f873c76

File tree

23 files changed

+307
-54
lines changed

23 files changed

+307
-54
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ Release notes
120120
simplicity, and readability.
121121
https://github.com/aboutcode-org/dejacode/issues/241
122122

123+
- Refine the way the PURL fragments are handled in searches.
124+
https://github.com/aboutcode-org/dejacode/issues/286
125+
123126
### Version 5.2.1
124127

125128
- Fix the models documentation navigation.

component_catalog/admin.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
from dje.templatetags.dje_tags import urlize_target_blank
7272
from dje.utils import CHANGELIST_LINK_TEMPLATE
7373
from dje.utils import get_instance_from_referer
74+
from dje.utils import is_purl_fragment
7475
from license_library.models import License
7576
from reporting.filters import ReportingQueryListFilter
7677

@@ -774,7 +775,17 @@ class PackageAdmin(
774775
"get_dataspace",
775776
)
776777
list_display_links = ("identifier",)
777-
search_fields = ("filename", "download_url", "project")
778+
search_fields = (
779+
"type",
780+
"namespace",
781+
"name",
782+
"version",
783+
"filename",
784+
"download_url",
785+
"sha1",
786+
"md5",
787+
"project",
788+
)
778789
ordering = ("-last_modified_date",)
779790
list_filter = (
780791
("component", HierarchyRelatedLookupListFilter),
@@ -912,6 +923,7 @@ def get_queryset(self, request):
912923
return (
913924
super()
914925
.get_queryset(request)
926+
.annotate_sortable_identifier()
915927
.select_related(
916928
"usage_policy",
917929
)
@@ -938,6 +950,16 @@ def get_urls(self):
938950

939951
return urls + super().get_urls()
940952

953+
def get_search_results(self, request, queryset, search_term):
954+
"""Add searching on provided PackageURL identifier."""
955+
use_distinct = False
956+
957+
if is_purl_fragment(search_term):
958+
if results := queryset.for_package_url(search_term):
959+
return results, use_distinct
960+
961+
return super().get_search_results(request, queryset, search_term)
962+
941963
def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
942964
"""
943965
Add the `show_save_and_collect_data` in the context.
@@ -1053,6 +1075,10 @@ def inferred_url(self, obj):
10531075
return urlize_target_blank(inferred_url)
10541076
return ""
10551077

1078+
@admin.display(ordering="sortable_identifier")
1079+
def identifier(self, obj):
1080+
return obj.identifier
1081+
10561082
def save_formset(self, request, form, formset, change):
10571083
"""
10581084
Update the completion_level on the related Component at the end of the saving process.

component_catalog/filters.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from dje.filters import HasRelationFilter
2323
from dje.filters import MatchOrderedSearchFilter
2424
from dje.filters import RelatedLookupListFilter
25+
from dje.utils import is_purl_fragment
2526
from dje.widgets import BootstrapSelectMultipleWidget
2627
from dje.widgets import DropDownRightWidget
2728
from dje.widgets import SortDropDownWidget
@@ -183,9 +184,9 @@ def filter(self, qs, value):
183184
if not value:
184185
return qs
185186

186-
is_purl = "/" in value
187-
if is_purl:
188-
return qs.for_package_url(value)
187+
if is_purl_fragment(value):
188+
if results := qs.for_package_url(value):
189+
return results
189190

190191
return super().filter(qs, value)
191192

component_catalog/tests/test_admin.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from component_catalog.models import Package
3535
from component_catalog.models import PackageAssignedLicense
3636
from component_catalog.models import Subcomponent
37+
from component_catalog.tests import make_package
3738
from dje.copier import copy_object
3839
from dje.filters import DataspaceFilter
3940
from dje.models import Dataspace
@@ -1650,6 +1651,8 @@ def test_package_changelist_advanced_search_on_protocol(self):
16501651
p2 = Package.objects.create(
16511652
filename="p2", download_url="https://url.com/p2.zip", dataspace=self.dataspace1
16521653
)
1654+
package_url = "pkg:pypi/[email protected]"
1655+
package3 = make_package(self.dataspace1, package_url)
16531656

16541657
self.client.login(username="test", password="secret")
16551658
changelist_url = reverse("admin:component_catalog_package_changelist")
@@ -1663,6 +1666,16 @@ def test_package_changelist_advanced_search_on_protocol(self):
16631666
self.assertEqual(1, response.context_data["cl"].result_count)
16641667
self.assertIn(p2, response.context_data["cl"].result_list)
16651668

1669+
response = self.client.get(changelist_url + f"?q={package_url}")
1670+
self.assertEqual(200, response.status_code)
1671+
self.assertEqual(1, response.context_data["cl"].result_count)
1672+
self.assertIn(package3, response.context_data["cl"].result_list)
1673+
1674+
response = self.client.get(changelist_url + "?q=pypi/django")
1675+
self.assertEqual(200, response.status_code)
1676+
self.assertEqual(1, response.context_data["cl"].result_count)
1677+
self.assertIn(package3, response.context_data["cl"].result_list)
1678+
16661679
def test_package_changelist_set_policy_action_proper(self):
16671680
self.client.login(username=self.user.username, password="secret")
16681681
p1 = Package.objects.create(filename="p1.zip", dataspace=self.dataspace1)

component_catalog/tests/test_views.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -642,41 +642,42 @@ def test_component_catalog_list_view_sort_keep_active_filters(self):
642642
# Sort filter
643643
self.assertContains(
644644
response,
645-
'<a href="?q=a&amp;licenses=license1&sort=name" class="sort" aria-label="Sort">',
645+
'<a href="?q=a&amp;licenses=license1&sort=name" class="sort ms-1" aria-label="Sort">',
646646
)
647647
# Sort in the headers
648648
self.assertContains(
649649
response,
650-
'<a href="?q=a&amp;licenses=license1&sort=name" class="sort" aria-label="Sort">',
650+
'<a href="?q=a&amp;licenses=license1&sort=name" class="sort ms-1" aria-label="Sort">',
651651
)
652652
self.assertContains(
653653
response,
654-
'<a href="?q=a&amp;licenses=license1&sort=primary_language" class="sort" '
654+
'<a href="?q=a&amp;licenses=license1&sort=primary_language" class="sort ms-1" '
655655
'aria-label="Sort">',
656656
)
657657

658658
data["sort"] = "name"
659659
response = self.client.get(url, data=data)
660660
self.assertContains(
661661
response,
662-
'<a href="?q=a&amp;licenses=license1&sort=-name" class="sort active" '
662+
'<a href="?q=a&amp;licenses=license1&sort=-name" class="sort active ms-1" '
663663
'aria-label="Sort">',
664664
)
665665
self.assertContains(
666666
response,
667-
'<a href="?q=a&amp;licenses=license1&sort=primary_language" class="sort" '
667+
'<a href="?q=a&amp;licenses=license1&sort=primary_language" class="sort ms-1" '
668668
'aria-label="Sort">',
669669
)
670670

671671
data["sort"] = "-name"
672672
response = self.client.get(url, data=data)
673673
self.assertContains(
674674
response,
675-
'<a href="?q=a&amp;licenses=license1&sort=name" class="sort active" aria-label="Sort">',
675+
'<a href="?q=a&amp;licenses=license1&sort=name" class="sort active ms-1" '
676+
'aria-label="Sort">',
676677
)
677678
self.assertContains(
678679
response,
679-
'<a href="?q=a&amp;licenses=license1&sort=primary_language" class="sort" '
680+
'<a href="?q=a&amp;licenses=license1&sort=primary_language" class="sort ms-1" '
680681
'aria-label="Sort">',
681682
)
682683

dejacode/static/css/dejacode_bootstrap.css

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -426,19 +426,22 @@ table.vulnerabilities-table .column-summary {
426426

427427
/* -- Dependency tab -- */
428428
#tab_dependencies .column-for_package {
429-
width: 250px;
429+
min-width: 300px;
430430
}
431431
#tab_dependencies .column-resolved_to_package {
432-
width: 250px;
432+
min-width: 300px;
433433
}
434434
#tab_dependencies .column-is_runtime {
435-
width: 100px;
435+
width: 85px;
436+
font-size: 0.75rem;
436437
}
437-
#tab_dependencies .column-column-is_optional {
438-
width: 100px;
438+
#tab_dependencies .column-is_optional {
439+
width: 85px;
440+
font-size: 0.75rem;
439441
}
440-
#tab_dependencies .column-column-is_pinned {
441-
width: 88px;
442+
#tab_dependencies .column-is_pinned {
443+
width: 80px;
444+
font-size: 0.75rem;
442445
}
443446

444447
/* -- Package Details -- */
@@ -661,7 +664,6 @@ td.sub-header {
661664
.table thead tr th a.sort:hover {
662665
color: #ccc;
663666
text-decoration: none;
664-
margin-left: 0;
665667
}
666668
.table thead tr th a.sort.active {
667669
color: var(--bs-body-color);

dje/admin.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,11 @@ def set_reference_link(self, request):
429429
params = f"?{DataspaceFilter.parameter_name}={reference_dataspace.id}"
430430
self.reference_params = params
431431

432+
def get_search_fields_for_hint_display(self):
433+
if not self.search_fields:
434+
return []
435+
return tuple(set(field.split("__")[0] for field in self.search_fields))
436+
432437

433438
class DataspacedAdmin(
434439
DataspacedFKMixin,

dje/dashboard.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515

1616

1717
class DejaCodeDashboard(Dashboard):
18+
short_description = (
19+
"The Administration section of DejaCode is intended primarily for application "
20+
"administrators (superusers) to maintain the data that supports organization "
21+
"policies and to configure the experience of the general user.\n"
22+
"Most of the routine activities regarding products, packages, components, "
23+
"licenses and owners can be performed in the User View section of DejaCode."
24+
)
25+
1826
def init_with_context(self, context):
1927
user = context["request"].user
2028
dataspace = user.dataspace

dje/templates/admin/change_list_extended.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ <h1>Browse {{ cl.opts.verbose_name_plural|capfirst }}</h1>
9696
{% if cl.search_fields %}
9797
$("#grp-changelist-search-form")
9898
.attr("style", "width: 90%;")
99-
.attr("data-hint", "Search fields: {{ cl.search_fields|join:', ' }}")
100-
.addClass("hint--bottom");
99+
.attr("data-hint", "Search fields: {{ cl.get_search_fields_for_hint_display|join:', ' }}")
100+
.addClass("hint--bottom hint--large");
101101
{% endif %}
102102

103103
// Opens actions listed in `target_blank_actions` in a new tab.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{% load i18n grp_dashboard_tags %}
2+
3+
{{ dashboard.media }}
4+
5+
{# DJE CUSTOM #}
6+
{% if dashboard.short_description %}
7+
<div id="short_description" class="g-d-c" style="margin-bottom:10px;">
8+
<p style="padding-right:10px;">
9+
{{ dashboard.short_description|linebreaksbr }}
10+
</p>
11+
</div>
12+
{% endif %}
13+
{# /DJE CUSTOM #}
14+
15+
<div class="g-d-c">
16+
<div class="g-d-12 g-d-f" id="column_1">
17+
{% for module in dashboard.children %}
18+
{% if module.column == 1 %}
19+
{% grp_render_dashboard_module module forloop.counter %}
20+
{% endif %}
21+
{% endfor %}
22+
</div>
23+
<div class="g-d-6" id="column_2">
24+
{% for module in dashboard.children %}
25+
{% if module.column == 2 %}
26+
{% grp_render_dashboard_module module forloop.counter %}
27+
{% endif %}
28+
{% endfor %}
29+
</div>
30+
<div class="g-d-6 g-d-l" id="column_3">
31+
{% for module in dashboard.children %}
32+
{% if module.column == 3 %}
33+
{% grp_render_dashboard_module module forloop.counter %}
34+
{% endif %}
35+
{% endfor %}
36+
</div>
37+
</div>

0 commit comments

Comments
 (0)