|
98 | 98 | </div> |
99 | 99 | <div id="resizer" class="resizer"></div> |
100 | 100 | <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 %} |
102 | 106 | </div> |
103 | 107 | </div> |
104 | 108 | {% endblock %} |
105 | 109 |
|
106 | 110 | {% block scripts %} |
107 | 111 | <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) { |
120 | 122 | 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"); |
125 | 127 | } |
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"); |
130 | 135 | } |
| 136 | + } |
131 | 137 |
|
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); |
152 | 145 | } |
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" }); |
158 | 151 | } |
159 | 152 |
|
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); |
174 | 167 | } |
175 | 168 | }); |
176 | 169 |
|
177 | 170 | document.addEventListener("DOMContentLoaded", function() { |
| 171 | + expandToPath("{{ path }}"); |
| 172 | + |
178 | 173 | const resizer = document.getElementById('resizer'); |
179 | 174 | const leftPane = document.getElementById('left-pane'); |
180 | 175 | const rightPane = document.getElementById('right-pane'); |
|
0 commit comments