Skip to content

Commit 010692d

Browse files
authored
Move resource path in the URL path instead of query string (#1945)
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 37172d5 commit 010692d

File tree

11 files changed

+122
-84
lines changed

11 files changed

+122
-84
lines changed

scancodeio/static/main.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@
146146
cursor: not-allowed;
147147
color: var(--bulma-text-weak);
148148
}
149+
.tabs.is-narrow {
150+
--bulma-tabs-link-padding: 0.5em 0.75em;
151+
}
149152
.border-no-top-left-radius {
150153
border-bottom-left-radius: 6px;
151154
border-bottom-right-radius: 6px;
@@ -340,6 +343,10 @@ a[target="_blank"] .fa-up-right-from-square {
340343
#content-header input[name="search"] {
341344
width: 225px;
342345
}
346+
.is-borderless {
347+
--bulma-button-border-width: 0px;
348+
--bulma-button-outer-shadow-a: 0;
349+
}
343350
button.as-link {
344351
height: auto;
345352
line-height: initial;

scanpipe/templates/scanpipe/panels/project_codebase.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</a>
99
</div>
1010
{% for node in codebase_root_tree %}
11-
<a class="panel-block" href="{% url 'project_resource_tree' project.slug %}?path={{ node.name }}">
11+
<a class="panel-block" href="{% url 'project_resource_tree' project.slug node.name %}">
1212
<span class="panel-icon">
1313
<i class="{% if node.is_dir %}fa-solid fa-folder{% else %}fa-regular fa-file{% endif %}"></i>
1414
</span>

scanpipe/templates/scanpipe/project_detail.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
</li>
2222
<li class="is-active">
2323
<a href="#" aria-current="page">{{ project.name }}</a>
24+
<button class="button is-borderless has-text-grey copy-to-clipboard p-2" aria-label="Copy name" data-copy="{{ project.name }}" data-copy-feedback="Name copied!">
25+
<i class="fa-regular fa-clone"></i>
26+
</button>
2427
</li>
2528
</ul>
2629
</nav>

scanpipe/templates/scanpipe/resource_tree.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,17 @@
2727
</div>
2828
<div id="resizer" class="resizer"></div>
2929
<div id="right-pane" class="right-pane px-3">
30-
{% if path %}
3130
<div
3231
{% if resource.is_file %}
3332
hx-get="{% url 'resource_detail' project.slug resource.path %}"
33+
{% elif path %}
34+
hx-get="{% url 'project_resource_tree_right_pane' project.slug path %}"
3435
{% else %}
35-
hx-get="{% url 'project_resource_tree_table' project.slug %}?path={{ path }}"
36+
hx-get="{% url 'project_resource_tree_right_pane' project.slug %}"
3637
{% endif %}
3738
hx-trigger="load"
3839
hx-target="this">
3940
</div>
40-
{% else %}
41-
{% include "scanpipe/tree/resource_right_pane.html" %}
42-
{% endif %}
4341
</div>
4442
</div>
4543
</div>
@@ -65,7 +63,9 @@
6563
}
6664
} else {
6765
target.classList.remove("is-hidden");
68-
const response = await fetch(url + "&tree_panel=true");
66+
const fullUrl = new URL(url, window.location.origin);
67+
fullUrl.searchParams.append('tree_panel', 'true');
68+
const response = await fetch(fullUrl.toString());
6969
target.innerHTML = await response.text();
7070
target.dataset.loaded = "true";
7171
htmx.process(target);

scanpipe/templates/scanpipe/tabset/tabset.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% load humanize %}
2-
<div class="tabs is-boxed mb-3">
2+
<div class="tabs is-boxed is-narrow mb-3">
33
<ul>
44
{% for tab_id, tab_data in tabset_data.items %}
55
<li{% if forloop.first %} class="is-active"{% endif %}>

scanpipe/templates/scanpipe/tree/resource_left_pane_tree.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
{% for node in children %}
33
<li>
44
{% if node.is_dir %}
5-
<div class="tree-node is-flex is-align-items-center px-1" data-folder data-path="{{ node.path }}"{% if node.has_children %} data-target="{{ node.path|slugify }}" data-url="{% url 'project_resource_tree' slug=project.slug %}?path={{ node.path }}"{% endif %}>
5+
<div class="tree-node is-flex is-align-items-center px-1" data-folder data-path="{{ node.path }}"{% if node.has_children %} data-target="{{ node.path|slugify }}" data-url="{% url 'project_resource_tree' project.slug node.path %}"{% endif %}>
66
<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>
77
<i class="fas fa-chevron-right"></i>
88
</span>
99
<span
1010
class="is-flex is-align-items-center folder-meta is-clickable"
1111
data-folder-click
1212
data-path="{{ node.path }}"
13-
hx-get="{% url 'project_resource_tree_table' project.slug %}?path={{ node.path }}"
13+
hx-get="{% url 'project_resource_tree_right_pane' project.slug node.path %}"
1414
hx-target="#right-pane"
15-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ node.path }}">
15+
hx-push-url="{% url 'project_resource_tree' project.slug node.path %}">
1616
<span class="icon is-small mr-2">
1717
<i class="fas fa-folder"></i>
1818
</span>
@@ -29,7 +29,7 @@
2929
data-path="{{ node.path }}"
3030
hx-get="{% url 'resource_detail' project.slug node.path %}"
3131
hx-target="#right-pane"
32-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ node.path }}">
32+
hx-push-url="{% url 'project_resource_tree' project.slug node.path %}">
3333
<span class="icon is-small mr-2">
3434
<i class="far fa-file"></i>
3535
</span>
Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
{% if path_segments %}
21
<nav class="breadcrumb is-flex is-align-items-center mb-2" aria-label="breadcrumbs">
32
<button
43
id="expand-left-pane"
@@ -7,31 +6,32 @@
76
data-tooltip-position="bottom right">
87
<i class="fa-solid fa-square-caret-right"></i>
98
</button>
10-
<ul>
11-
{% for subpath, segment in path_segments %}
12-
{% if not forloop.last %}
13-
<li>
14-
<a
15-
href="{% url 'project_resource_tree' project.slug %}?path={{ subpath }}"
16-
class="expand-in-tree"
17-
data-path="{{ subpath }}"
18-
hx-get="{% url 'project_resource_tree_table' project.slug %}?path={{ subpath }}"
19-
hx-target="#right-pane"
20-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ subpath }}">
21-
{{ segment }}
22-
</a>
23-
</li>
24-
{% else %}
25-
<li class="is-active">
26-
<a href="#" class="has-text-dark" aria-current="page">
27-
{{ segment }}
28-
</a>
29-
</li>
30-
{% endif %}
31-
{% endfor %}
32-
</ul>
33-
<button class="button is-white copy-to-clipboard p-2" aria-label="Copy path" data-copy="{{ path }}" data-copy-feedback="Path copied!">
34-
<i class="fa-regular fa-clone"></i>
35-
</button>
36-
</nav>
37-
{% endif %}
9+
{% if path %}
10+
<ul>
11+
{% for subpath, segment in path_segments %}
12+
{% if not forloop.last %}
13+
<li>
14+
<a
15+
href="{% url 'project_resource_tree' project.slug subpath %}"
16+
class="expand-in-tree"
17+
data-path="{{ subpath }}"
18+
hx-get="{% url 'project_resource_tree_right_pane' project.slug subpath %}"
19+
hx-target="#right-pane"
20+
hx-push-url="{% url 'project_resource_tree' project.slug subpath %}">
21+
{{ segment }}
22+
</a>
23+
</li>
24+
{% else %}
25+
<li class="is-active">
26+
<a href="#" class="has-text-dark" aria-current="page">
27+
{{ segment }}
28+
</a>
29+
</li>
30+
{% endif %}
31+
{% endfor %}
32+
</ul>
33+
<button class="button is-borderless copy-to-clipboard p-2" aria-label="Copy path" data-copy="{{ path }}" data-copy-feedback="Path copied!">
34+
<i class="fa-regular fa-clone"></i>
35+
</button>
36+
{% endif %}
37+
</nav>

scanpipe/templates/scanpipe/tree/resource_table.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<table class="table is-bordered is-hoverable is-fullwidth">
33
<thead class="is-sticky">
44
<tr>
5-
<th>Name</th>
5+
<th style="min-width:200px;">Name</th>
66
<th>Status</th>
77
<th>Language</th>
88
<th>License</th>
@@ -14,9 +14,9 @@
1414
<tr
1515
class="expand-in-tree is-clickable"
1616
data-path="{{ parent_path }}"
17-
hx-get="{% url 'project_resource_tree_table' project.slug %}{% if parent_path %}?path={{ parent_path }}{% endif %}"
17+
hx-get="{% url 'project_resource_tree_right_pane' project.slug parent_path %}"
1818
hx-target="#right-pane"
19-
hx-push-url="{% url 'project_resource_tree' project.slug %}{% if parent_path %}?path={{ parent_path }}{% endif %}">
19+
hx-push-url="{% url 'project_resource_tree' project.slug parent_path %}">
2020
<td colspan="5">
2121
<div class="is-flex is-align-items-center">
2222
<span class="icon is-small mr-2">
@@ -41,19 +41,19 @@
4141
{% if resource.is_dir %}
4242
<a
4343
class="expand-in-tree"
44-
href="{% url 'project_resource_tree' project.slug %}?path={{ resource.path }}"
44+
href="{% url 'project_resource_tree' project.slug resource.path %}"
4545
data-path="{{ resource.path }}"
46-
hx-get="{% url 'project_resource_tree_table' project.slug %}?path={{ resource.path }}"
46+
hx-get="{% url 'project_resource_tree_right_pane' project.slug resource.path %}"
4747
hx-target="#right-pane"
48-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ resource.path }}">
48+
hx-push-url="{% url 'project_resource_tree' project.slug resource.path %}">
4949
{{ resource.name }}
5050
</a>
5151
{% else %}
5252
<a
5353
href="{% url 'resource_detail' project.slug resource.path %}"
5454
hx-get="{% url 'resource_detail' project.slug resource.path %}"
5555
hx-target="#right-pane"
56-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ resource.path }}">
56+
hx-push-url="{% url 'project_resource_tree' project.slug resource.path %}">
5757
{{ resource.name }}
5858
</a>
5959
{% endif %}
@@ -84,18 +84,18 @@
8484
{% if page_obj.has_previous %}
8585
<a
8686
class="pagination-previous"
87-
hx-get="{% url 'project_resource_tree_table' project.slug %}?path={{ path }}&page={{ page_obj.previous_page_number }}"
87+
hx-get="{% url 'project_resource_tree_right_pane' project.slug path %}?page={{ page_obj.previous_page_number }}"
8888
hx-target="#right-pane"
89-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ path }}&page={{ page_obj.previous_page_number }}">
89+
hx-push-url="{% url 'project_resource_tree' project.slug path %}?page={{ page_obj.previous_page_number }}">
9090
Previous
9191
</a>
9292
{% endif %}
9393
{% if page_obj.has_next %}
9494
<a
9595
class="pagination-next"
96-
hx-get="{% url 'project_resource_tree_table' project.slug %}?path={{ path }}&page={{ page_obj.next_page_number }}"
96+
hx-get="{% url 'project_resource_tree_right_pane' project.slug path%}?page={{ page_obj.next_page_number }}"
9797
hx-target="#right-pane"
98-
hx-push-url="{% url 'project_resource_tree' project.slug %}?path={{ path }}&page={{ page_obj.next_page_number }}">
98+
hx-push-url="{% url 'project_resource_tree' project.slug path %}?page={{ page_obj.next_page_number }}">
9999
Next page
100100
</a>
101101
{% endif %}

scanpipe/tests/test_views.py

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -672,12 +672,17 @@ def test_scanpipe_views_project_codebase_view(self):
672672

673673
(self.project1.codebase_path / "dir1").mkdir()
674674
(self.project1.codebase_path / "dir1/dir2").mkdir()
675-
(self.project1.codebase_path / "file.txt").touch()
675+
(self.project1.codebase_path / "file+.txt").touch()
676676

677677
response = self.client.get(url)
678-
resource_tree_url = reverse("project_resource_tree", args=[self.project1.slug])
679-
self.assertContains(response, f"{resource_tree_url}?path=dir1")
680-
self.assertContains(response, f"{resource_tree_url}?path=file.txt")
678+
resource_tree_url = reverse(
679+
"project_resource_tree", args=[self.project1.slug, "dir1"]
680+
)
681+
self.assertContains(response, resource_tree_url)
682+
resource_tree_url = reverse(
683+
"project_resource_tree", args=[self.project1.slug, "file+.txt"]
684+
)
685+
self.assertContains(response, resource_tree_url)
681686

682687
def test_scanpipe_views_project_codebase_view_ordering(self):
683688
url = reverse("project_codebase", args=[self.project1.slug])
@@ -1622,8 +1627,11 @@ def test_scanpipe_views_resource_tree_children_path(self):
16221627
make_resource_file(self.project1, path="parent/dir1")
16231628
make_resource_file(self.project1, path="parent/dir1/child2.txt")
16241629

1625-
url = reverse("project_resource_tree", kwargs={"slug": self.project1.slug})
1626-
response = self.client.get(url + "?path=parent&tree_panel=true")
1630+
url = reverse(
1631+
"project_resource_tree",
1632+
kwargs={"slug": self.project1.slug, "path": "parent"},
1633+
)
1634+
response = self.client.get(url + "?tree_panel=true")
16271635
children = response.context["children"]
16281636

16291637
child1 = children[0]
@@ -1635,66 +1643,76 @@ def test_scanpipe_views_resource_tree_children_path(self):
16351643
self.assertFalse(child1.has_children)
16361644
self.assertTrue(dir1.has_children)
16371645

1638-
def test_scanpipe_views_project_resource_tree_table_view_with_path_directory(self):
1639-
make_resource_directory(self.project1, path="parent")
1640-
make_resource_file(self.project1, path="parent/child1.txt")
1641-
make_resource_file(self.project1, path="parent/child2.py")
1646+
def test_scanpipe_views_project_resource_tree_right_pane_view_with_path_directory(
1647+
self,
1648+
):
1649+
resource1 = make_resource_directory(self.project1, path="parent+special&chars")
1650+
make_resource_file(self.project1, path="parent+special&chars/child1.txt")
1651+
make_resource_file(self.project1, path="parent+special&chars/child2.py")
16421652

16431653
url = reverse(
1644-
"project_resource_tree_table", kwargs={"slug": self.project1.slug}
1654+
"project_resource_tree_right_pane",
1655+
kwargs={"slug": self.project1.slug, "path": resource1.path},
16451656
)
1646-
response = self.client.get(url + "?path=parent")
1657+
response = self.client.get(url)
16471658

16481659
self.assertEqual(200, response.status_code)
1649-
self.assertEqual("parent", response.context["path"])
1660+
self.assertEqual(resource1.path, response.context["path"])
16501661
resources = list(response.context["resources"])
16511662
self.assertEqual(2, len(resources))
16521663

16531664
resource_paths = [r.path for r in resources]
1654-
self.assertEqual(["parent/child1.txt", "parent/child2.py"], resource_paths)
1665+
self.assertEqual(
1666+
["parent+special&chars/child1.txt", "parent+special&chars/child2.py"],
1667+
resource_paths,
1668+
)
16551669

16561670
def test_scanpipe_views_project_resource_tree_view_with_path_file(self):
16571671
resource = make_resource_file(self.project1, path="specific_file.txt")
16581672

1659-
url = reverse("project_resource_tree", kwargs={"slug": self.project1.slug})
1660-
response = self.client.get(url + f"?path={resource.path}")
1673+
url = reverse(
1674+
"project_resource_tree",
1675+
kwargs={"slug": self.project1.slug, "path": resource.path},
1676+
)
1677+
response = self.client.get(url)
16611678

16621679
self.assertEqual(200, response.status_code)
16631680
self.assertEqual("specific_file.txt", response.context["path"])
16641681
self.assertEqual(resource, response.context["resource"])
16651682

1666-
def test_scanpipe_views_project_resource_tree_table_view_empty_directory(self):
1683+
def test_scanpipe_views_project_resource_tree_right_pane_view_empty_directory(self):
16671684
make_resource_directory(self.project1, path="empty_dir")
16681685

16691686
url = reverse(
1670-
"project_resource_tree_table", kwargs={"slug": self.project1.slug}
1687+
"project_resource_tree_right_pane",
1688+
kwargs={"slug": self.project1.slug, "path": "empty_dir"},
16711689
)
1672-
response = self.client.get(url + "?path=empty_dir")
1673-
1690+
response = self.client.get(url)
16741691
self.assertEqual(200, response.status_code)
16751692
self.assertEqual("empty_dir", response.context["path"])
16761693
resources = list(response.context["resources"])
16771694
self.assertEqual(0, len(resources))
16781695

1679-
@mock.patch("scanpipe.views.ProjectResourceTreeTableView.paginate_by", 2)
1680-
def test_scanpipe_views_project_resource_tree_table_view_pagination(self):
1696+
@mock.patch("scanpipe.views.ProjectResourceTreeRightPaneView.paginate_by", 2)
1697+
def test_scanpipe_views_project_resource_tree_right_pane_view_pagination(self):
16811698
make_resource_directory(self.project1, path="parent")
16821699
make_resource_file(self.project1, path="parent/file1.txt", parent_path="parent")
16831700
make_resource_file(self.project1, path="parent/file2.txt", parent_path="parent")
16841701
make_resource_file(self.project1, path="parent/file3.txt", parent_path="parent")
16851702

16861703
url = reverse(
1687-
"project_resource_tree_table", kwargs={"slug": self.project1.slug}
1704+
"project_resource_tree_right_pane",
1705+
kwargs={"slug": self.project1.slug, "path": "parent"},
16881706
)
16891707

1690-
response = self.client.get(url + "?path=parent")
1708+
response = self.client.get(url)
16911709
self.assertEqual(200, response.status_code)
16921710
self.assertTrue(response.context["is_paginated"])
16931711
self.assertEqual(1, response.context["page_obj"].number)
16941712
self.assertTrue(response.context["page_obj"].has_next())
16951713
self.assertFalse(response.context["page_obj"].has_previous())
16961714

1697-
response = self.client.get(url + "?path=parent&page=2")
1715+
response = self.client.get(url + "?page=2")
16981716
self.assertEqual(200, response.status_code)
16991717
self.assertEqual(2, response.context["page_obj"].number)
17001718
self.assertFalse(response.context["page_obj"].has_next())

0 commit comments

Comments
 (0)