Skip to content

Commit 3ce8f76

Browse files
committed
Track the current browsing path in the browser URL
Signed-off-by: Aayush Kumar <[email protected]>
1 parent 3d8700a commit 3ce8f76

File tree

4 files changed

+60
-64
lines changed

4 files changed

+60
-64
lines changed

scanpipe/templates/scanpipe/panels/codebase_tree_panel.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
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>
9-
<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">
9+
<span class="is-flex is-align-items-center folder-meta is-clickable" data-folder-click data-path="{{ node.path }}" hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ node.path }}" hx-target="#right-pane" hx-push-url="{% url 'codebase_resource_tree' project.slug %}?path={{ node.path }}">
1010
<span class="icon is-small mr-2">
1111
<i class="fas fa-folder"></i>
1212
</span>
@@ -17,7 +17,7 @@
1717
<div id="dir-{{ node.path|slugify }}" class="ml-4 is-hidden" data-loaded="false"></div>
1818
{% endif %}
1919
{% else %}
20-
<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">
20+
<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" hx-push-url="{% url 'codebase_resource_tree' project.slug %}?path={{ node.path }}">
2121
<span class="icon is-small mr-2">
2222
<i class="far fa-file"></i>
2323
</span>

scanpipe/templates/scanpipe/panels/resource_table_panel.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
{% endif %}
2424
</span>
2525
{% if resource.is_dir %}
26-
<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>
26+
<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" hx-push-url="{% url 'codebase_resource_tree' project.slug %}?path={{ resource.path }}">{{ resource.name }}</a>
2727
{% else %}
2828
<a href="{% url 'resource_detail' project.slug resource.path %}">{{ resource.name }}</a>
2929
{% endif %}

scanpipe/templates/scanpipe/resource_tree.html

Lines changed: 55 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -98,83 +98,78 @@
9898
</div>
9999
<div id="resizer" class="resizer"></div>
100100
<div id="right-pane" class="right-pane px-2">
101-
{% include "scanpipe/panels/resource_table_panel.html" %}
101+
{% if path %}
102+
<div hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ path }}" hx-trigger="load" hx-target="this"></div>
103+
{% else %}
104+
{% include "scanpipe/panels/resource_table_panel.html" %}
105+
{% endif %}
102106
</div>
103107
</div>
104108
{% endblock %}
105109

106110
{% block scripts %}
107111
<script>
108-
// Tree functionality
109-
document.addEventListener("click", async function (e) {
110-
const chevron = e.target.closest("[data-chevron]");
111-
if (chevron) {
112-
const folderNode = chevron.closest("[data-folder]");
113-
const targetId = folderNode.dataset.target;
114-
const url = folderNode.dataset.url;
115-
const target = document.getElementById("dir-" + targetId);
116-
117-
if (target.dataset.loaded === "true") {
118-
target.classList.toggle("is-hidden");
119-
} else {
112+
async function toggleFolderNode(folderNode, forceExpand = false) {
113+
const targetId = folderNode.dataset.target;
114+
const url = folderNode.dataset.url;
115+
const target = document.getElementById("dir-" + targetId);
116+
const chevron = folderNode.querySelector("[data-chevron]");
117+
118+
if (!target || !chevron) return;
119+
120+
if (target.dataset.loaded === "true") {
121+
if (forceExpand) {
120122
target.classList.remove("is-hidden");
121-
const response = await fetch(url + "&tree_panel=true");
122-
target.innerHTML = await response.text();
123-
target.dataset.loaded = "true";
124-
htmx.process(target);
123+
chevron.classList.add("rotated");
124+
} else {
125+
target.classList.toggle("is-hidden");
126+
chevron.classList.toggle("rotated");
125127
}
126-
127-
chevron.classList.toggle("rotated");
128-
e.stopPropagation();
129-
return;
128+
} else {
129+
target.classList.remove("is-hidden");
130+
const response = await fetch(url + "&tree_panel=true");
131+
target.innerHTML = await response.text();
132+
target.dataset.loaded = "true";
133+
htmx.process(target);
134+
chevron.classList.add("rotated");
130135
}
136+
}
131137

132-
const folderMeta = e.target.closest(".folder-meta");
133-
if (folderMeta) {
134-
const folderNode = folderMeta.closest("[data-folder]");
135-
if (folderNode && folderNode.dataset.target) {
136-
document.querySelectorAll('.tree-node.is-current, .is-file.is-current').forEach(el => el.classList.remove('is-current'));
137-
folderNode.classList.add('is-current');
138-
const chevron = folderNode.querySelector("[data-chevron]");
139-
const target = document.getElementById("dir-" + folderNode.dataset.target);
140-
141-
if (target.classList.contains("is-hidden")) {
142-
target.classList.remove("is-hidden");
143-
chevron.classList.add("rotated");
144-
if (target.dataset.loaded !== "true") {
145-
const response = await fetch(folderNode.dataset.url + "&tree_panel=true");
146-
target.innerHTML = await response.text();
147-
target.dataset.loaded = "true";
148-
htmx.process(target);
149-
}
150-
}
151-
}
138+
async function expandToPath(path) {
139+
const parts = path.split('/').filter(Boolean);
140+
let current = "";
141+
for (const part of parts) {
142+
current = current ? current + "/" + part : part;
143+
const folderNode = document.querySelector(`[data-folder][data-path="${current}"]`);
144+
if (folderNode) await toggleFolderNode(folderNode, true);
152145
}
153-
154-
const fileNode = e.target.closest(".is-file[data-file]");
155-
if (fileNode) {
156-
document.querySelectorAll('.tree-node.is-current, .is-file.is-current').forEach(el => el.classList.remove('is-current'));
157-
fileNode.classList.add('is-current');
146+
const finalNode = document.querySelector(`[data-folder][data-path="${path}"], .is-file[data-file][data-path="${path}"]`);
147+
if (finalNode) {
148+
document.querySelectorAll('.is-current').forEach(el => el.classList.remove('is-current'));
149+
finalNode.classList.add('is-current');
150+
finalNode.scrollIntoView({ behavior: "smooth", block: "center" });
158151
}
159152

160-
const expandLink = e.target.closest(".expand-in-tree");
161-
if (expandLink) {
162-
e.preventDefault();
163-
const path = expandLink.getAttribute("data-path");
164-
const leftPane = document.getElementById("left-pane");
165-
if (!leftPane) return;
166-
let node = leftPane.querySelector(`[data-folder][data-path="${path}"], .is-file[data-file][data-path="${path}"]`);
167-
if (node) {
168-
document.querySelectorAll('.tree-node.is-current, .is-file.is-current').forEach(el => el.classList.remove('is-current'));
169-
node.classList.add('is-current');
170-
const chevron = node.querySelector("[data-chevron]");
171-
if (chevron && !chevron.classList.contains("rotated")) chevron.click();
172-
node.scrollIntoView({behavior: "smooth", block: "center"});
173-
}
153+
const rightPane = document.getElementById('right-pane');
154+
rightPane.setAttribute('hx-get', `/project/{{ project.slug }}/resource_table/?path=${encodeURIComponent(path)}`);
155+
htmx.trigger(rightPane, 'htmx:trigger');
156+
}
157+
158+
document.addEventListener("click", async e => {
159+
const node = e.target.closest("[data-folder], .is-file[data-file], .expand-in-tree, [data-chevron]");
160+
if (!node) return;
161+
162+
e.preventDefault();
163+
if (node.matches("[data-chevron]")) {
164+
await toggleFolderNode(node.closest("[data-folder]"));
165+
} else if (node.matches("[data-folder], .is-file[data-file], .expand-in-tree")) {
166+
await expandToPath(node.dataset.path);
174167
}
175168
});
176169

177170
document.addEventListener("DOMContentLoaded", function() {
171+
expandToPath("{{ path }}");
172+
178173
const resizer = document.getElementById('resizer');
179174
const leftPane = document.getElementById('left-pane');
180175
const rightPane = document.getElementById('right-pane');

scanpipe/views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2767,9 +2767,10 @@ def get(self, request, *args, **kwargs):
27672767
slug = self.kwargs.get("slug")
27682768
project = get_object_or_404(Project, slug=slug)
27692769
path = request.GET.get("path", "")
2770+
parent_path = path if request.GET.get("tree_panel") == "true" else ""
27702771

27712772
children = (
2772-
project.codebaseresources.filter(parent_path=path)
2773+
project.codebaseresources.filter(parent_path=parent_path)
27732774
.with_has_children()
27742775
.only("id", "project_id", "path", "name", "type")
27752776
.order_by("type", "path")

0 commit comments

Comments
 (0)