Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ v35.4.0 (unreleased)
- Add new ``benchmark_purls`` pipeline.
https://github.com/aboutcode-org/scancode.io/issues/1804

- Add a Resources tree view.
https://github.com/aboutcode-org/scancode.io/issues/1682

v35.3.0 (2025-08-20)
--------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@
<a href="{{ project_resources_url }}">
{{ project.resource_count|intcomma }}
</a>
{% if project.resource_count > 1 %}
<a href="{% url 'codebase_resource_tree' project.slug %}" class="ml-2">
<span class="icon">
<i class="fa-solid fa-folder-tree is-size-6"></i>
</span>
</a>
{% endif %}
{% if project.resource_compliance_alert_count %}
<a href="{% url 'project_resources' project.slug %}?compliance_alert=error" class="has-text-danger is-size-5 ml-2">
{{ project.resource_compliance_alert_count|intcomma }}
Expand Down
8 changes: 4 additions & 4 deletions scanpipe/templates/scanpipe/panels/codebase_tree_panel.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<ul>
{% for node in children %}
<li class="mb-1">
<li>
{% if node.is_dir %}
<div class="tree-node is-flex is-align-items-center has-text-weight-semibold px-1" data-folder data-path="{{ node.path }}"{% if node.has_children %} data-target="{{ node.path|slugify }}" data-url="{% url 'codebase_resource_tree' slug=project.slug %}?path={{ node.path }}"{% endif %}>
<span class="icon is-small chevron mr-1{% if not node.has_children %} is-invisible{% endif %} is-clickable is-flex is-align-items-center" data-chevron>
<i class="fas fa-chevron-right"></i>
</span>
<span class="is-flex is-align-items-center folder-meta is-clickable" data-folder-click hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ node.path }}" hx-target="#right-pane">
<span class="icon is-small mr-1">
<span class="icon is-small mr-2">
<i class="fas fa-folder"></i>
</span>
<span>{{ node.name }}</span>
Expand All @@ -17,8 +17,8 @@
<div id="dir-{{ node.path|slugify }}" class="ml-4 is-hidden" data-loaded="false"></div>
{% endif %}
{% else %}
<div class="is-flex is-align-items-center ml-5 is-clickable is-file" data-file data-path="{{ node.path }}" hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ node.path }}" hx-target="#right-pane">
<span class="icon is-small mr-1">
<div class="tree-node-file is-flex is-align-items-center pl-5 is-clickable is-file" data-file data-path="{{ node.path }}" hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ node.path }}" hx-target="#right-pane">
<span class="icon is-small mr-2">
<i class="far fa-file"></i>
</span>
<span>{{ node.name }}</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<article id="license-clarity-panel" class="panel is-info">
<article id="license-clarity-panel" class="panel is-dark">
<div class="panel-heading is-flex is-justify-content-space-between">
License clarity
{% include "scanpipe/dropdowns/help_dropdown_tooltip.html" with content="License clarity is a set of metrics that indicate how clearly, comprehensively and accurately a software project has defined and communicated the licensing that applies to the software." only %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{% load humanize %}
{% if license_detection_summary %}
<div class="column is-half">
<article id="license-detection-summary-panel" class="panel is-info">
<article id="license-detection-summary-panel" class="panel is-dark">
<div class="panel-heading is-flex is-justify-content-space-between">
Unique license detections
{% include "scanpipe/dropdowns/help_dropdown_tooltip.html" with content="All unique license detections in the codebase identified by matched license text and other license match characteristics. Also contains other license clues." only %}
</div>
<div class="panel is-info">
<nav class="panel is-info">
<div class="panel is-dark">
<nav class="panel is-dark">
{% for license_expression, count in license_detection_summary.items %}
<a class="panel-block is-align-items-flex-start break-word is-flex is-align-items-center" href="{{ project_licenses_url }}?license_expression={{ license_expression|default:'_EMPTY_' }}" target="_blank">
{{ license_expression|default:'<i>No licenses</i>' }}
Expand Down
36 changes: 19 additions & 17 deletions scanpipe/templates/scanpipe/panels/project_codebase.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
<nav id="codebase-navigation" class="panel is-dark">
<p class="panel-heading is-flex is-justify-content-space-between is-align-items-center">
<span>Codebase</span>
<div class="panel-heading is-flex is-justify-content-space-between is-align-items-center">
<div>
<span>Codebase</span>
{% if current_dir and current_dir != "." %}
<span class="tag ml-2">
{% for dir_name, full_path in codebase_breadcrumbs.items %}
{% if not forloop.last %}
<a href="#" hx-target="#codebase-navigation" hx-swap="outerHTML" hx-get="{{ project_details_url }}codebase/?current_dir={{ full_path }}">
{{ dir_name }}
</a>
<span class="mr-1">/</span>
{% else %}
{{ dir_name }}/
{% endif %}
{% endfor %}
</span>
{% endif %}
</div>
<a href="{% url 'codebase_resource_tree' project.slug %}" class="ml-2 has-text-white has-text-decoration-none">
<i class="fa-solid fa-folder-tree mr-1"></i>Tree view
</a>
{% if current_dir and current_dir != "." %}
<span class="tag ml-2">
{% for dir_name, full_path in codebase_breadcrumbs.items %}
{% if not forloop.last %}
<a href="#" hx-target="#codebase-navigation" hx-swap="outerHTML" hx-get="{{ project_details_url }}codebase/?current_dir={{ full_path }}">
{{ dir_name }}
</a>
<span class="mr-1">/</span>
{% else %}
{{ dir_name }}/
{% endif %}
{% endfor %}
</span>
{% endif %}
</p>
</div>
{% for node in codebase_tree %}
{% if node.is_dir %}
<a class="panel-block" href="#" hx-target="#codebase-navigation" hx-swap="outerHTML" hx-get="{{ project_details_url }}codebase/?current_dir={{ node.location }}">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% load humanize %}
{% if resource_status_summary %}
<div class="column is-half">
<nav class="panel is-info">
<nav class="panel is-dark">
<p class="panel-heading">
Resources status
</p>
Expand Down
69 changes: 23 additions & 46 deletions scanpipe/templates/scanpipe/panels/resource_table_panel.html
Original file line number Diff line number Diff line change
@@ -1,75 +1,48 @@
{% load humanize %}

{% if resources %}
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
<table class="table is-bordered is-striped is-narrow is-fullwidth">
<thead class="is-sticky">
<tr>
<th>Path</th>
<th>Status</th>
<th>Type</th>
<th>Size</th>
<th>Name</th>
<th>Extension</th>
<th>Status</th>
<th>Language</th>
<th>MIME Type</th>
<th>Tag</th>
<th>License</th>
<th>Alert</th>
<th>Packages</th>
</tr>
</thead>
<tbody>
{% for resource in resources %}
<tr>
<td class="break-all" style="min-width: 200px;">
{% if resource.is_dir %}
<a href="#" class="expand-in-tree" data-path="{{ resource.path }}" hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ resource.path }}" hx-target="#right-pane">{{ resource.path }}</a>
{% else %}
<a href="{% url 'resource_detail' project.slug resource.path %}">{{ resource.path }}</a>
{% endif %}
<td class="is-flex is-align-items-center break-all" style="min-width: 100px;">
<span class="icon is-small mr-2">
{% if resource.is_dir %}
<i class="fas fa-folder"></i>
{% else %}
<i class="far fa-file"></i>
{% endif %}
</span>
{% if resource.is_dir %}
<a href="#" class="expand-in-tree" data-path="{{ resource.path }}" hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ resource.path }}" hx-target="#right-pane">{{ resource.name }}</a>
{% else %}
<a href="{% url 'resource_detail' project.slug resource.path %}">{{ resource.name }}</a>
{% endif %}
{% if resource.tag %}
<span class="tag is-rounded ml-2">{{ resource.tag }}</span>
{% endif %}
</td>
<td>
{{ resource.status }}
</td>
<td>
{{ resource.type }}
</td>
<td>
{% if resource.is_file %}
{{ resource.size|filesizeformat|default_if_none:"" }}
{% endif %}
</td>
<td class="break-all" style="min-width: 100px;">
{{ resource.name }}
</td>
<td>
{{ resource.extension }}
</td>
<td class="break-all">
{{ resource.programming_language }}
</td>
<td class="break-all">
{{ resource.mime_type }}
</td>
<td>
{{ resource.tag }}
</td>
<td>
{{ resource.detected_license_expression }}
</td>
<td>
{{ resource.compliance_alert }}
</td>
<td>
{% if resource.discovered_packages.all %}
{% for package in resource.discovered_packages.all|slice:":3" %}
<a href="{% url 'project_packages' project.slug %}?purl={{ package.package_url }}">{{ package }}</a>{% if not forloop.last %}, {% endif %}
{% endfor %}
{% if resource.discovered_packages.all|length > 3 %}
+{{ resource.discovered_packages.all|length|add:"-3" }} more
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Expand All @@ -84,7 +57,11 @@
<a class="pagination-next" hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ path }}&page={{ page_obj.next_page_number }}" hx-target="#right-pane">Next page</a>
{% endif %}
<ul class="pagination-list">
<li><span class="pagination-ellipsis">Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span></li>
<li>
<span class="pagination-ellipsis">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
</li>
</ul>
</nav>
{% endif %}
Expand Down
4 changes: 2 additions & 2 deletions scanpipe/templates/scanpipe/panels/scan_summary_panel.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% load intcomma from humanize %}
<article id="scan-summary-panel" class="panel is-info">
<div class="panel-heading py-2 is-size-6 is-flex is-justify-content-space-between">
<article id="scan-summary-panel" class="panel is-dark">
<div class="panel-heading is-size-6 is-flex is-justify-content-space-between">
Scan summary
{% include "scanpipe/dropdowns/help_dropdown_tooltip.html" with content="A top-level summary of the collected scanned data such as licenses, holders, and languages." only %}
</div>
Expand Down
2 changes: 1 addition & 1 deletion scanpipe/templates/scanpipe/project_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
</div>

{% if object_list %}
{% include 'scanpipe/includes/project_list_table.html' with projects=object_list %}
{% include 'scanpipe/tables/project_list_table.html' with projects=object_list %}
{% else %}
<article class="box has-text-centered border-dashed">
{% if filter.is_active %}
Expand Down
6 changes: 6 additions & 0 deletions scanpipe/templates/scanpipe/resource_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
</div>

<div id="resource-list" class="container is-fluid mb-3">
<a href="{% url 'codebase_resource_tree' project.slug %}" class="is-pulled-right">
<span class="icon">
<i class="fa-solid fa-folder-tree"></i>
</span>
<span>View the resource tree</span>
</a>
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
{% include 'scanpipe/includes/list_view_thead.html' %}
<tbody>
Expand Down
50 changes: 26 additions & 24 deletions scanpipe/templates/scanpipe/resource_tree.html
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
{% extends "scanpipe/base.html" %}
{% load static humanize %}
{% block title %}ScanCode.io: {{ project.name }} - Resource Tree{% endblock %}
{% block title %}ScanCode.io: {{ project.name }} - Resources tree{% endblock %}

{% block extrahead %}
<style>
.is-current {
background: rgba(128,128,128,0.10);
border-radius: 6px;
}
.chevron {
transition: transform 0.2s ease;
display: inline-block;
}
.chevron.rotated {
transform: rotate(90deg);
}

.resizable-container {
display: flex;
height: calc(100vh - 140px);
margin: 0;
}

.left-pane {
min-width: 0;
max-width: 100%;
Expand All @@ -30,49 +24,59 @@
overflow-x: hidden;
flex-basis: 25%;
transition: opacity 0.2s ease;
text-overflow: ellipsis;
white-space: nowrap;
}

.left-pane.collapsed {
opacity: 0;
pointer-events: none;
}

.resizer {
width: 5px;
width: 3px;
background: #ddd;
cursor: col-resize;
position: relative;
flex-shrink: 0;
}

.resizer:hover {
background: #bbb;
}

.resizer::before {
content: '';
position: absolute;
top: 50%;
left: 1px;
left: 0px;
transform: translateY(-50%);
width: 3px;
width: 2px;
height: 30px;
background: #999;
border-radius: 2px;
}

.right-pane {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-width: 0;
transition: opacity 0.2s ease;
}

.right-pane.collapsed {
opacity: 0;
pointer-events: none;
}
.right-pane a:hover {
text-decoration: underline;
}
.is-current, .is-current:hover {
background-color: var(--bulma-background-hover) !important;
border-radius: var(--bulma-radius);
}
.tree-node, .tree-node-file {
padding: .25rem 0 .25rem 0;
}
.tree-node:hover, .tree-node-file:hover {
background-color: var(--bulma-background);
border-radius: var(--bulma-radius);
}
</style>
{% endblock %}

Expand All @@ -81,22 +85,20 @@
{% include 'scanpipe/includes/navbar_header.html' %}
<section class="mx-5">
<div class="is-flex is-justify-content-space-between">
{% include 'scanpipe/includes/breadcrumb.html' with linked_project=True current="Resource Tree" %}
{% include 'scanpipe/includes/breadcrumb.html' with linked_project=True current="Resources tree" %}
</div>
</section>
</div>

<div class="resizable-container">
<div class="left-pane" id="left-pane">
<div id="resource-tree" class="p-4">
<div id="left-pane" class="left-pane px-2">
<div id="resource-tree">
{% include "scanpipe/panels/codebase_tree_panel.html" with children=children path=path %}
</div>
</div>
<div class="resizer" id="resizer"></div>
<div class="right-pane" id="right-pane">
<div class="p-4">
{% include "scanpipe/panels/resource_table_panel.html" %}
</div>
<div id="resizer" class="resizer"></div>
<div id="right-pane" class="right-pane px-2">
{% include "scanpipe/panels/resource_table_panel.html" %}
</div>
</div>
{% endblock %}
Expand Down
Loading