11{% extends "scanpipe/base.html" %}
2+ {% load static %}
23
34{% block title %}ScanCode.io: {{ project.name }} - Dependency tree{% endblock %}
45
6+ {% block extrahead %}
7+ < link rel ="stylesheet " href ="{% static 'iamkate-tree-views/tree.css' %} " crossorigin ="anonymous ">
8+ < style >
9+ .tree {
10+ line-height : 1.8rem ;
11+ --spacing : 2rem ;
12+ }
13+ .tree summary {
14+ display : inline-block;
15+ }
16+ .tree summary ::before {
17+ background-color : rgb (72 , 199 , 142 );
18+ background-image : url ('{% static "iamkate-tree-views/expand-collapse.svg" %}' );
19+ }
20+ </ style >
21+ {% endblock %}
22+
523{% block content %}
624 < div id ="content-header " class ="container is-max-widescreen mb-3 ">
725 {% include 'scanpipe/includes/navbar_header.html' %}
1331 </ div >
1432
1533 < div class ="container is-max-widescreen mb-3 ">
16- {% if recursion_error %}
17- < article class ="message is-danger ">
18- < div class ="message-body ">
19- The dependency tree cannot be rendered as it contains circular references.
20- {{ message|linebreaksbr }}
21- </ div >
22- </ article >
23- {% endif %}
24- < div id ="tree "> </ div >
34+ < section class ="mx-5 ">
35+ {% if recursion_error %}
36+ < article class ="message is-danger ">
37+ < div class ="message-body ">
38+ The dependency tree cannot be rendered as it contains circular references.
39+ {{ message|linebreaksbr }}
40+ </ div >
41+ </ article >
42+ {% endif %}
43+
44+ < div class ="mb-4 ">
45+ < button id ="collapseAll " class ="button is-small ">
46+ < span > Collapse All</ span >
47+ < span class ="icon is-small ">
48+ < i class ="fas fa-minus "> </ i >
49+ </ span >
50+ </ button >
51+ < button id ="expendAll " class ="button is-small ">
52+ < span > Expend All</ span >
53+ < span class ="icon is-small ">
54+ < i class ="fas fa-plus "> </ i >
55+ </ span >
56+ </ button >
57+ < button id ="showVulnerableOnlyButton " class ="button is-small ">
58+ < span > Show Vulnerable only</ span >
59+ < span class ="icon is-small ">
60+ < i class ="fa-solid fa-bug "> </ i >
61+ </ span >
62+ </ button >
63+ < button id ="showComplianceAlertOnlyButton " class ="button is-small ">
64+ < span > Show Compliance Alert only</ span >
65+ < span class ="icon is-small ">
66+ < i class ="fa-solid fa-scale-balanced "> </ i >
67+ </ span >
68+ </ button >
69+ </ div >
70+
71+ < ul id ="tree " class ="tree ">
72+ < li >
73+ < details open >
74+ < summary class ="has-text-weight-semibold ">
75+ {{ dependency_tree.name }}
76+ </ summary >
77+ {% include 'scanpipe/tree/dependency_children.html' with children=dependency_tree.children %}
78+ </ details >
79+ </ li >
80+ </ ul >
81+ </ section >
2582 </ div >
2683{% endblock %}
2784
2885{% block scripts %}
29- < script src ="https://d3js.org/d3.v7.min.js "> </ script >
30- < script src ="https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6 "> </ script >
31- {{ dependency_tree|json_script:"dependency_tree" }}
32- {{ row_count|json_script:"row_count" }}
33- {{ max_depth|json_script:"max_depth" }}
34- < script >
35- const data = JSON . parse ( document . getElementById ( "dependency_tree" ) . textContent ) ;
36- const hierarchyData = d3 . hierarchy ( data ) ;
37- const columnWidth = 110 ;
38- const rowWidth = 25 ;
39- const columnCount = hierarchyData . height ;
40- const rowCount = hierarchyData . links ( ) . length ;
41- const width = columnWidth * ( columnCount + 1 ) ;
42- const height = rowWidth * ( rowCount + 1 ) ;
43-
44- function indent ( ) {
45- return ( root ) => {
46- root . eachBefore ( ( node , i ) => {
47- node . y = node . depth ;
48- node . x = i ;
49- } ) ;
50- } ;
86+ < script >
87+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
88+ const treeContainer = document . getElementById ( 'tree' ) ;
89+ const collapseAllButton = document . getElementById ( 'collapseAll' ) ;
90+ const expendAllButton = document . getElementById ( 'expendAll' ) ;
91+
92+ function collapseAllDetails ( ) {
93+ document . querySelectorAll ( 'details' ) . forEach ( details => {
94+ details . removeAttribute ( 'open' ) ;
95+ } ) ;
96+ showAllListItems ( ) ;
97+ }
98+
99+ function expendAllDetails ( ) {
100+ document . querySelectorAll ( 'details' ) . forEach ( details => {
101+ details . setAttribute ( 'open' , '' ) ; // Adding 'open' attribute to open the details
102+ } ) ;
103+ showAllListItems ( ) ;
104+ }
105+
106+ collapseAllButton . addEventListener ( 'click' , collapseAllDetails ) ;
107+ expendAllButton . addEventListener ( 'click' , expendAllDetails ) ;
108+
109+ // Following function are use to limit the display to specific elements.
110+
111+ function expandAncestors ( detailsElement ) {
112+ let parent = detailsElement . parentElement . closest ( 'details' ) ;
113+ while ( parent ) {
114+ parent . setAttribute ( 'open' , '' ) ;
115+ parent . parentElement . style . display = '' ;
116+ parent = parent . parentElement . closest ( 'details' ) ;
117+ }
118+ }
119+
120+ function showAllListItems ( ) {
121+ const listItems = treeContainer . querySelectorAll ( 'li' ) ;
122+ listItems . forEach ( item => {
123+ item . style . display = '' ;
124+ } ) ;
125+ }
126+
127+ function hideAllListItems ( ) {
128+ const listItems = treeContainer . querySelectorAll ( 'li' ) ;
129+ listItems . forEach ( item => {
130+ item . style . display = 'none' ;
131+ } ) ;
132+ }
133+
134+ function handleItems ( attribute , value ) {
135+ collapseAllDetails ( ) ;
136+ hideAllListItems ( ) ;
137+
138+ const items = document . querySelectorAll ( `li[${ attribute } ="${ value } "]` ) ;
139+ items . forEach ( item => {
140+ item . style . display = 'block' ;
141+ expandAncestors ( item ) ;
142+ } ) ;
143+ }
144+
145+ function handleVulnerableItems ( ) {
146+ handleItems ( 'data-is-vulnerable' , 'true' ) ;
147+ }
148+
149+ function handleComplianceAlertItems ( ) {
150+ handleItems ( 'data-compliance-alert' , 'true' ) ;
51151 }
52152
53- // https://observablehq.com/plot/marks/tree
54- const plot = Plot . plot ( {
55- axis : null ,
56- margin : 10 ,
57- marginLeft : 40 ,
58- marginRight : 160 ,
59- width : width ,
60- height : height ,
61- marks : [
62- Plot . tree ( hierarchyData . leaves ( ) , {
63- path : ( node ) => node . ancestors ( ) . reverse ( ) . map ( ( { data : { name } } ) => name ) . join ( "|" ) ,
64- delimiter : "|" ,
65- treeLayout : indent ,
66- strokeWidth : 1 ,
67- curve : "step-before" ,
68- fontSize : 14 ,
69- textStroke : "none"
70- } )
71- ]
72- } ) ;
73-
74- document . getElementById ( "tree" ) . appendChild ( plot ) ;
75- </ script >
153+ showVulnerableOnlyButton . addEventListener ( 'click' , handleVulnerableItems ) ;
154+ showComplianceAlertOnlyButton . addEventListener ( 'click' , handleComplianceAlertItems ) ;
155+ } ) ;
156+ </ script >
76157{% endblock %}
0 commit comments