1+ {% load i18n %}
2+ < div class ="row g-4 mb-4 ">
3+ {# License panel #}
4+ < div class ="col-lg-6 ">
5+ < div class ="border rounded-3 p-3 h-100 ">
6+ < div class ="d-flex justify-content-between align-items-center mb-3 ">
7+ < h3 class ="fs-6 fw-medium mb-0 "> {% trans "License compliance" %}</ h3 >
8+ {% if license_issues_count == 0 %}
9+ < span class ="badge text-bg-success ">
10+ {% trans "OK" %}
11+ </ span >
12+ {% elif license_error_count > 0 %}
13+ < span class ="badge text-bg-danger ">
14+ {% trans "Error" %}
15+ </ span >
16+ {% else %}
17+ < span class ="badge text-bg-warning ">
18+ {% trans "Warning" %}
19+ </ span >
20+ {% endif %}
21+ </ div >
22+
23+ < p class ="text-secondary small mb-2 ">
24+ {% trans "License distribution" %} (top {{ license_distribution_limit }})
25+ </ p >
26+ < table class ="table table-sm mb-0 ">
27+ < thead >
28+ < tr >
29+ < th class ="fw-medium "> {% trans "License" %}</ th >
30+ < th class ="fw-medium text-end "> {% trans "Packages" %}</ th >
31+ < th class ="fw-medium text-end "> {% trans "Policy" %}</ th >
32+ </ tr >
33+ </ thead >
34+ < tbody >
35+ {% for license in license_distribution %}
36+ < tr >
37+ < td >
38+ < a href ="{% url 'license_library:license_details' product.dataspace.name license.key %} ">
39+ {{ license.spdx_license_key }}
40+ </ a >
41+ </ td >
42+ < td class ="text-end ">
43+ < a href ="{{ product.get_absolute_url }}?inventory-licenses={{ license.key }}#inventory ">
44+ {{ license.package_count }}
45+ </ a >
46+ </ td >
47+ < td class ="text-end ">
48+ {% if license.compliance_alert == "error" %}
49+ < span class ="badge text-bg-danger "> {% trans "Error" %}</ span >
50+ {% elif license.compliance_alert == "warning" %}
51+ < span class ="badge text-bg-warning "> {% trans "Warning" %}</ span >
52+ {% else %}
53+ < span class ="badge text-bg-success "> {% trans "OK" %}</ span >
54+ {% endif %}
55+ </ td >
56+ </ tr >
57+ {% endfor %}
58+ </ tbody >
59+ </ table >
60+ {% if remaining_license_count > 0 %}
61+ < div class =" mt-2 pt-2 ">
62+ < small class ="text-body-tertiary ">
63+ + {{ remaining_license_count }} {% trans "other license" %}{{ remaining_license_count|pluralize }}{% if license_issues_count == 0 %}, {% trans "all within policy" %}{% endif %}
64+ </ small >
65+ </ div >
66+ {% endif %}
67+ </ div >
68+ </ div >
69+
70+ {# Security panel #}
71+ < div class ="col-lg-6 ">
72+ < div class ="border rounded-3 p-3 h-100 ">
73+ {# Header #}
74+ < div class ="d-flex justify-content-between align-items-center mb-3 ">
75+ < h3 class ="fs-6 fw-medium mb-0 "> {% trans "Security compliance" %}</ h3 >
76+ {% if vulnerability_count == 0 or above_threshold_count == 0 %}
77+ < span class ="badge text-bg-success "> {% trans "OK" %}</ span >
78+ {% elif max_vulnerability_severity == "critical" %}
79+ < span class ="badge text-bg-danger "> {% trans "Critical" %}</ span >
80+ {% elif max_vulnerability_severity == "high" %}
81+ < span class ="badge bg-warning-orange "> {% trans "High" %}</ span >
82+ {% elif max_vulnerability_severity == "medium" %}
83+ < span class ="badge text-bg-warning "> {% trans "Medium" %}</ span >
84+ {% else %}
85+ < span class ="badge text-bg-info "> {% trans "Low" %}</ span >
86+ {% endif %}
87+ </ div >
88+
89+ {# Summary #}
90+ {% if vulnerability_count > 0 %}
91+ < p class ="text-body-secondary small mb-3 ">
92+ {% if risk_threshold_number %}
93+ {% if above_threshold_count > 0 %}
94+ {{ above_threshold_count }} {% trans "of" %} {{ vulnerability_count }}
95+ {% trans "vulnerabilit" %}{{ vulnerability_count|pluralize:"y,ies" }}
96+ {% trans "above risk threshold of" %} {{ risk_threshold_number }}
97+ {% else %}
98+ {{ vulnerability_count }}
99+ {% trans "vulnerabilit" %}{{ vulnerability_count|pluralize:"y,ies" }},
100+ {% trans "all below risk threshold of" %} {{ risk_threshold_number }}
101+ {% endif %}
102+ {% else %}
103+ {{ vulnerability_count }}
104+ {% trans "vulnerabilit" %}{{ vulnerability_count|pluralize:"y,ies" }}
105+ — {% trans "no risk threshold set" %}
106+ {% endif %}
107+ </ p >
108+ {% endif %}
109+
110+ {# Vulnerability list #}
111+ {% for vulnerability in vulnerabilities %}
112+ < div class ="d-flex align-items-center border-bottom gap-3 py-2 ">
113+ < span data-bs-toggle ="tooltip " title ="{{ vulnerability.risk_score }} ">
114+ {% if vulnerability.risk_level == "critical" %}
115+ < span class ="badge text-bg-danger "> {% trans "Critical" %}</ span >
116+ {% elif vulnerability.risk_level == "high" %}
117+ < span class ="badge bg-warning-orange "> {% trans "High" %}</ span >
118+ {% elif vulnerability.risk_level == "medium" %}
119+ < span class ="badge text-bg-warning "> {% trans "Medium" %}</ span >
120+ {% elif vulnerability.risk_level == "low" %}
121+ < span class ="badge text-bg-info "> {% trans "Low" %}</ span >
122+ {% else %}
123+ < span class ="badge text-bg-secondary "> {% trans "Unknown" %}</ span >
124+ {% endif %}
125+ </ span >
126+ < a href ="{{ vulnerability.resource_url }} " target ="_blank " class ="font-monospace small text-decoration-none " style ="min-width: fit-content; ">
127+ {{ vulnerability.vulnerability_id }}
128+ </ a >
129+ < span class ="flex-grow-1 d-none d-md-inline small "> {{ vulnerability.summary|truncatechars:70 }}</ span >
130+ </ div >
131+ {% empty %}
132+ < div class ="text-center text-body-tertiary py-4 ">
133+ < i class ="fas fa-shield-check fa-2x mb-2 d-block "> </ i >
134+ {% trans "No known vulnerabilities" %}
135+ </ div >
136+ {% endfor %}
137+
138+ {# View all link #}
139+ {% if vulnerabilities|length < vulnerability _count %}
140+ < div class ="mt-2 ">
141+ < a href ="#vulnerabilities " class ="text-decoration-none small " onclick ="new bootstrap.Tab(document.querySelector('#tab_vulnerabilities-tab')).show() ">
142+ {% trans "View all" %} {{ vulnerability_count }} {% trans "vulnerabilities" %}
143+ < i class ="fas fa-arrow-right ms-1 "> </ i >
144+ </ a >
145+ </ div >
146+ {% endif %}
147+ </ div >
148+ </ div >
149+ </ div >
0 commit comments