|
104 | 104 | </div> |
105 | 105 | <div id="resizer" class="resizer"></div> |
106 | 106 | <div id="right-pane" class="right-pane px-2"> |
107 | | - {% include "scanpipe/panels/resource_table_panel.html" %} |
| 107 | + {% if path %} |
| 108 | + <div hx-get="{% url 'codebase_resource_table' project.slug %}?path={{ path }}" hx-trigger="load" hx-target="this"></div> |
| 109 | + {% else %} |
| 110 | + {% include "scanpipe/panels/resource_table_panel.html" %} |
| 111 | + {% endif %} |
108 | 112 | </div> |
109 | 113 | </div> |
110 | 114 | {% endblock %} |
111 | 115 |
|
112 | 116 | {% block scripts %} |
113 | 117 | <script> |
114 | | - document.body.addEventListener('htmx:afterSwap', function(evt) { |
115 | | - if (evt.target && evt.target.id === 'right-pane') { |
116 | | - if (typeof enableCopyToClipboard === 'function') { |
117 | | - enableCopyToClipboard('.copy-to-clipboard'); |
118 | | - } |
| 118 | + document.body.addEventListener('htmx:afterSettle', function(evt) { |
| 119 | + if (typeof enableCopyToClipboard === 'function') { |
| 120 | + enableCopyToClipboard('.copy-to-clipboard'); |
119 | 121 | } |
120 | 122 | }); |
121 | | - |
122 | | - // Tree functionality |
123 | | - document.addEventListener("click", async function (e) { |
124 | | - const chevron = e.target.closest("[data-chevron]"); |
125 | | - if (chevron) { |
126 | | - const folderNode = chevron.closest("[data-folder]"); |
127 | | - const targetId = folderNode.dataset.target; |
128 | | - const url = folderNode.dataset.url; |
129 | | - const target = document.getElementById("dir-" + targetId); |
130 | | - |
131 | | - if (target.dataset.loaded === "true") { |
132 | | - target.classList.toggle("is-hidden"); |
133 | | - } else { |
134 | | - target.classList.remove("is-hidden"); |
135 | | - const response = await fetch(url + "&tree_panel=true"); |
136 | | - target.innerHTML = await response.text(); |
137 | | - target.dataset.loaded = "true"; |
138 | | - htmx.process(target); |
139 | | - } |
140 | 123 |
|
141 | | - chevron.classList.toggle("rotated"); |
142 | | - e.stopPropagation(); |
143 | | - return; |
144 | | - } |
| 124 | + async function toggleFolderNode(folderNode, forceExpand = false) { |
| 125 | + const targetId = folderNode.dataset.target; |
| 126 | + const url = folderNode.dataset.url; |
| 127 | + const target = document.getElementById("dir-" + targetId); |
| 128 | + const chevron = folderNode.querySelector("[data-chevron]"); |
| 129 | + |
| 130 | + if (!target || !chevron) return; |
145 | 131 |
|
146 | | - const folderMeta = e.target.closest(".folder-meta"); |
147 | | - if (folderMeta) { |
148 | | - const folderNode = folderMeta.closest("[data-folder]"); |
149 | | - if (folderNode && folderNode.dataset.target) { |
150 | | - document.querySelectorAll('.tree-node.is-current, .is-file.is-current').forEach(el => el.classList.remove('is-current')); |
151 | | - folderNode.classList.add('is-current'); |
152 | | - const chevron = folderNode.querySelector("[data-chevron]"); |
153 | | - const target = document.getElementById("dir-" + folderNode.dataset.target); |
154 | | - |
155 | | - if (target.classList.contains("is-hidden")) { |
156 | | - target.classList.remove("is-hidden"); |
157 | | - chevron.classList.add("rotated"); |
158 | | - if (target.dataset.loaded !== "true") { |
159 | | - const response = await fetch(folderNode.dataset.url + "&tree_panel=true"); |
160 | | - target.innerHTML = await response.text(); |
161 | | - target.dataset.loaded = "true"; |
162 | | - htmx.process(target); |
163 | | - } |
164 | | - } |
| 132 | + if (target.dataset.loaded === "true") { |
| 133 | + if (forceExpand) { |
| 134 | + target.classList.remove("is-hidden"); |
| 135 | + chevron.classList.add("rotated"); |
| 136 | + } else { |
| 137 | + target.classList.toggle("is-hidden"); |
| 138 | + chevron.classList.toggle("rotated"); |
165 | 139 | } |
| 140 | + } else { |
| 141 | + target.classList.remove("is-hidden"); |
| 142 | + const response = await fetch(url + "&tree_panel=true"); |
| 143 | + target.innerHTML = await response.text(); |
| 144 | + target.dataset.loaded = "true"; |
| 145 | + htmx.process(target); |
| 146 | + chevron.classList.add("rotated"); |
166 | 147 | } |
| 148 | + } |
167 | 149 |
|
168 | | - const fileNode = e.target.closest(".is-file[data-file]"); |
169 | | - if (fileNode) { |
170 | | - document.querySelectorAll('.tree-node.is-current, .is-file.is-current').forEach(el => el.classList.remove('is-current')); |
171 | | - fileNode.classList.add('is-current'); |
| 150 | + async function expandToPath(path) { |
| 151 | + const parts = path.split('/').filter(Boolean); |
| 152 | + let current = ""; |
| 153 | + for (const part of parts) { |
| 154 | + current = current ? current + "/" + part : part; |
| 155 | + const folderNode = document.querySelector(`[data-folder][data-path="${current}"]`); |
| 156 | + if (folderNode) await toggleFolderNode(folderNode, true); |
| 157 | + } |
| 158 | + const finalNode = document.querySelector(`[data-folder][data-path="${path}"], .is-file[data-file][data-path="${path}"]`); |
| 159 | + if (finalNode) { |
| 160 | + document.querySelectorAll('.is-current').forEach(el => el.classList.remove('is-current')); |
| 161 | + finalNode.classList.add('is-current'); |
| 162 | + finalNode.scrollIntoView({ behavior: "smooth", block: "center" }); |
172 | 163 | } |
| 164 | + } |
173 | 165 |
|
174 | | - const expandLink = e.target.closest(".expand-in-tree"); |
175 | | - if (expandLink) { |
176 | | - e.preventDefault(); |
177 | | - const path = expandLink.getAttribute("data-path"); |
178 | | - const leftPane = document.getElementById("left-pane"); |
179 | | - if (!leftPane) return; |
180 | | - let node = leftPane.querySelector(`[data-folder][data-path="${path}"], .is-file[data-file][data-path="${path}"]`); |
181 | | - if (node) { |
182 | | - document.querySelectorAll('.tree-node.is-current, .is-file.is-current').forEach(el => el.classList.remove('is-current')); |
183 | | - node.classList.add('is-current'); |
184 | | - const chevron = node.querySelector("[data-chevron]"); |
185 | | - if (chevron && !chevron.classList.contains("rotated")) chevron.click(); |
186 | | - node.scrollIntoView({behavior: "smooth", block: "center"}); |
187 | | - } |
| 166 | + document.addEventListener("click", async e => { |
| 167 | + const node = e.target.closest("[data-folder], .is-file[data-file], .expand-in-tree, [data-chevron]"); |
| 168 | + if (!node) return; |
| 169 | + |
| 170 | + e.preventDefault(); |
| 171 | + if (node.matches("[data-chevron]")) { |
| 172 | + await toggleFolderNode(node.closest("[data-folder]")); |
| 173 | + } else if (node.matches("[data-folder], .is-file[data-file], .expand-in-tree")) { |
| 174 | + await expandToPath(node.dataset.path); |
188 | 175 | } |
189 | 176 | }); |
190 | 177 |
|
191 | 178 | document.addEventListener("DOMContentLoaded", function() { |
| 179 | + const currentPath = "{{ path }}"; |
| 180 | + if (currentPath) { |
| 181 | + expandToPath(currentPath); |
| 182 | + } |
| 183 | + |
192 | 184 | const resizer = document.getElementById('resizer'); |
193 | 185 | const leftPane = document.getElementById('left-pane'); |
194 | 186 | const rightPane = document.getElementById('right-pane'); |
|
0 commit comments