Skip to content

Commit e1f35d2

Browse files
committed
Make the scan delete from inventory async using HTMX #222
Signed-off-by: tdruez <[email protected]>
1 parent eca6572 commit e1f35d2

File tree

7 files changed

+121
-40
lines changed

7 files changed

+121
-40
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{% load i18n %}
2+
<div id="scan-delete-modal" class="modal" tabindex="-1" role="dialog">
3+
<div class="modal-dialog" role="document">
4+
<div class="modal-content">
5+
<div class="modal-header">
6+
<h5 class="modal-title">Delete {% trans 'Scan' %}</h5>
7+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
8+
</div>
9+
<div class="modal-body bg-body-tertiary">
10+
<p><strong>Are you sure you want to delete this Scan?</strong></p>
11+
<p>
12+
All data and results related to the Scan will be deleted.<br>
13+
If the Scan is in progress, it will be canceled.
14+
</p>
15+
</div>
16+
<div class="modal-footer">
17+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
18+
Cancel
19+
</button>
20+
<button hx-delete=""
21+
hx-target=""
22+
hx-swap="outerHTML"
23+
hx-on--before-request="
24+
let target = document.querySelector(this.getAttribute('hx-target'));
25+
if (target) target.innerHTML = 'Deleting...';
26+
"
27+
hx-on--error="
28+
let target = document.querySelector(this.getAttribute('hx-target'));
29+
if (target) target.innerHTML = 'Error!';
30+
"
31+
class="btn btn-danger delete-confirm"
32+
data-bs-dismiss="modal">
33+
Delete Scan
34+
</button>
35+
</div>
36+
</div>
37+
</div>
38+
</div>

product_portfolio/templates/product_portfolio/product_details.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
{% endif %}
118118
{% if display_scan_features %}
119119
{% include 'component_catalog/includes/scan_package_modal.html' %}
120-
{% include 'component_catalog/includes/scan_delete_modal.html' %}
120+
{% include 'product_portfolio/modals/scan_delete_htmx_modal.html' %}
121121
{% endif %}
122122
{% if pull_project_data_form %}
123123
{% include 'product_portfolio/includes/pull_project_data_modal.html' %}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<span{% if package.download_url %} data-bs-toggle="modal" data-bs-target="#scan-package-modal" data-package-scan-url="{% url 'component_catalog:package_scan' user.dataspace package.uuid %}"{% endif %}>
2+
<span data-bs-toggle="tooltip" title="{% if package.download_url %}Submit Scan Request{% else %}Download URL not available{% endif %}">
3+
<button type="button" class="btn btn-outline-dark btn-sm{% if not package.download_url %} disabled{% endif %}">
4+
<i class="fas fa-barcode"></i> Scan
5+
</button>
6+
</span>
7+
</span>
Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
{% include 'component_catalog/includes/scan_status.html' with status=scan.runs.0.status only %}
2-
3-
<ul class="list-inline mt-1 mb-0">
4-
{% if view_url %}
5-
<li class="list-inline-item" data-bs-toggle="tooltip" data-bs-title="View Scan results">
6-
<a class="text-dark" href="{{ view_url }}#scan" target="_blank">
7-
<i class="far fa-file-alt"></i>
8-
</a>
9-
</li>
10-
{% endif %}
11-
{% if scan.download_result_url %}
12-
<li class="list-inline-item" data-bs-toggle="tooltip" data-bs-title="Download Scan results">
13-
<a class="text-dark" href="{{ scan.download_result_url }}" target="_blank">
14-
<i class="fas fa-download"></i>
15-
</a>
16-
</li>
17-
{% endif %}
18-
{% if scan.delete_url %}
19-
<li class="list-inline-item" data-bs-toggle="tooltip" data-bs-title="Delete Scan">
20-
<a class="text-dark scan_delete_link" href="#scan-delete-modal" role="button" data-delete-url="{{ scan.delete_url }}" data-bs-toggle="modal">
21-
<i class="far fa-trash-alt"></i>
22-
</a>
23-
</li>
24-
{% endif %}
25-
</ul>
1+
<div id="scan-progress-{{ scan.uuid }}">
2+
{% include 'component_catalog/includes/scan_status.html' with status=scan.runs.0.status only %}
3+
<ul class="list-inline mt-1 mb-0">
4+
{% if view_url %}
5+
<li class="list-inline-item" data-bs-toggle="tooltip" data-bs-title="View Scan results">
6+
<a class="text-dark" href="{{ view_url }}#scan" target="_blank">
7+
<i class="far fa-file-alt"></i>
8+
</a>
9+
</li>
10+
{% endif %}
11+
{% if scan.download_result_url %}
12+
<li class="list-inline-item" data-bs-toggle="tooltip" data-bs-title="Download Scan results">
13+
<a class="text-dark" href="{{ scan.download_result_url }}" target="_blank">
14+
<i class="fas fa-download"></i>
15+
</a>
16+
</li>
17+
{% endif %}
18+
{% if scan.delete_url %}
19+
<li class="list-inline-item" data-bs-toggle="tooltip" data-bs-title="Delete Scan">
20+
<a class="text-dark scan_delete_link" href="#scan-delete-modal" role="button" data-delete-url="{{ scan.delete_url }}" data-scan-uuid="{{ scan.uuid }}" data-bs-toggle="modal">
21+
<i class="far fa-trash-alt"></i>
22+
</a>
23+
</li>
24+
{% endif %}
25+
</ul>
26+
</div>

product_portfolio/templates/product_portfolio/tabs/tab_inventory.html

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
{% for relation in relationships %}
100100
{% cycle 'table-odd' '' as rowcolors silent %}
101101
<tr class="{{ rowcolors }}{% if show_licenses_policy and relation.inventory_item_compliance_alert %} {{ relation.compliance_table_class }}{% endif %}">
102-
<td{% if relation.package %} data-purl="{{ relation.package.package_url }}"{% endif %}>
102+
<td{% if relation.package %} data-purl="{{ relation.package.package_url }} data-package-uuid="{{ relation.package.uuid }}"{% endif %}>
103103
<ul class="list-inline float-end mb-0">
104104
{% if request.user.is_authenticated and is_user_dataspace and relation.related_component_or_package.request_count %}
105105
<li class="list-inline-item me-1">
@@ -146,17 +146,9 @@
146146
{% if display_scan_features %}
147147
<td>
148148
{% if relation.scan %}
149-
{% include 'product_portfolio/tables/scan_progress_cell.html' with scan=relation.scan view_url=relation.package.get_absolute_url compact_mode=True only %}
149+
{% include 'product_portfolio/tables/scan_progress_cell.html' with scan=relation.scan view_url=relation.package.get_absolute_url only %}
150150
{% elif relation.package %}
151-
{% with relation.package.download_url as download_url %}
152-
<span{% if download_url %} data-bs-toggle="modal" data-bs-target="#scan-package-modal" data-package-scan-url="{% url 'component_catalog:package_scan' user.dataspace relation.package.uuid %}"{% endif %}>
153-
<span data-bs-toggle="tooltip" title="{% if download_url %}{% trans 'Submit Scan Request' %}{% else %}{% trans 'Download URL not available' %}{% endif %}">
154-
<button type="button" class="btn btn-outline-dark btn-sm{% if not download_url %} disabled{% endif %}">
155-
<i class="fas fa-barcode"></i> Scan
156-
</button>
157-
</span>
158-
</span>
159-
{% endwith %}
151+
{% include 'product_portfolio/tables/scan_action_cell.html' with package=relation.package user=request.user only %}
160152
{% endif %}
161153
</td>
162154
{% endif %}
@@ -321,7 +313,12 @@
321313
document.querySelectorAll('.scan_delete_link').forEach(link => {
322314
link.addEventListener('click', function() {
323315
let deleteUrl = this.getAttribute('data-delete-url');
324-
document.querySelector('#scan-delete-modal a.delete-confirm').setAttribute('href', deleteUrl);
316+
let scanUUID = this.getAttribute('data-scan-uuid');
317+
let confirmButton = document.querySelector('#scan-delete-modal button.delete-confirm');
318+
319+
confirmButton.setAttribute('hx-delete', deleteUrl);
320+
confirmButton.setAttribute('hx-target', `#scan-progress-${scanUUID}`);
321+
htmx.process(confirmButton); // Notify HTMX about the hx-delete change.
325322
});
326323
});
327324
{% endif %}

product_portfolio/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from product_portfolio.views import PullProjectDataFromScanCodeIOView
3232
from product_portfolio.views import add_customcomponent_ajax_view
3333
from product_portfolio.views import check_package_version_ajax_view
34+
from product_portfolio.views import delete_scan_htmx_view
3435
from product_portfolio.views import edit_productrelation_ajax_view
3536
from product_portfolio.views import import_from_scan_view
3637
from product_portfolio.views import import_packages_from_scancodeio_view
@@ -86,6 +87,11 @@ def product_path(path_segment, view):
8687
vulnerability_analysis_form_view,
8788
name="vulnerability_analysis_form",
8889
),
90+
path(
91+
"scans/<uuid:project_uuid>/<uuid:package_uuid>/delete/",
92+
delete_scan_htmx_view,
93+
name="scan_delete_htmx",
94+
),
8995
*product_path("add_customcomponent_ajax", add_customcomponent_ajax_view),
9096
*product_path("vulnerability_analysis_form", vulnerability_analysis_form_view),
9197
*product_path("scan_all_packages", scan_all_packages_view),

product_portfolio/views.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from django.utils.html import format_html
4545
from django.utils.translation import gettext_lazy as _
4646
from django.views.decorators.csrf import csrf_exempt
47+
from django.views.decorators.http import require_http_methods
4748
from django.views.decorators.http import require_POST
4849
from django.views.generic import DetailView
4950
from django.views.generic import FormView
@@ -947,11 +948,12 @@ def inject_scan_data(scancodeio, feature_grouped, dataspace_uuid):
947948
for productpackage in productpackages:
948949
if not isinstance(productpackage, ProductPackage):
949950
continue
950-
scan = scans_by_uri.get(productpackage.package.download_url)
951+
package = productpackage.package
952+
scan = scans_by_uri.get(package.download_url)
951953
if scan:
952954
scan["download_result_url"] = get_scan_results_as_file_url(scan)
953955
scan["delete_url"] = reverse(
954-
"component_catalog:scan_delete", args=[scan.get("uuid")]
956+
"product_portfolio:scan_delete_htmx", args=[scan.get("uuid"), package.uuid]
955957
)
956958
productpackage.scan = scan
957959
injected_productpackages.append(productpackage)
@@ -2587,3 +2589,33 @@ def vulnerability_analysis_form_view(request, productpackage_uuid, vulnerability
25872589
rendered_form = render_crispy_form(form, context=csrf(request))
25882590

25892591
return HttpResponse(rendered_form)
2592+
2593+
2594+
@login_required
2595+
@csrf_exempt
2596+
@require_http_methods(["DELETE"])
2597+
def delete_scan_htmx_view(request, project_uuid, package_uuid):
2598+
template = "product_portfolio/tables/scan_action_cell.html"
2599+
dataspace = request.user.dataspace
2600+
package = get_object_or_404(Package, uuid=package_uuid, dataspace=dataspace)
2601+
2602+
if not dataspace.enable_package_scanning:
2603+
raise Http404
2604+
2605+
scancodeio = ScanCodeIO(dataspace)
2606+
scan_list = scancodeio.fetch_scan_list(uuid=str(project_uuid))
2607+
2608+
if not scan_list or scan_list.get("count") != 1:
2609+
raise Http404("Scan not found.")
2610+
2611+
scan_detail_url = scancodeio.get_scan_detail_url(project_uuid)
2612+
deleted = scancodeio.delete_scan(scan_detail_url)
2613+
2614+
if not deleted:
2615+
raise Http404("Scan could not be deleted.")
2616+
2617+
context = {
2618+
"package": package,
2619+
"user": request.user,
2620+
}
2621+
return render(request, template, context)

0 commit comments

Comments
 (0)