Merge pull request #118 from theta42/feat/directory-tree-only-and-click-detail

Directory: tree view is now the only view; click a name for detail
This commit is contained in:
2026-07-28 13:29:45 -04:00
committed by GitHub
+39 -45
View File
@@ -15,12 +15,6 @@
<option value="kind">Kind</option> <option value="kind">Kind</option>
<option value="env">Environment</option> <option value="env">Environment</option>
</select> </select>
<div class="btn-group btn-group-sm shadow-sm" role="group">
<input type="radio" class="btn-check" name="viewMode" id="view-list" value="list" autocomplete="off" checked onchange="renderTable()">
<label class="btn btn-outline-secondary" for="view-list"><i class="fa-solid fa-list"></i></label>
<input type="radio" class="btn-check" name="viewMode" id="view-tree" value="tree" autocomplete="off" onchange="renderTable()">
<label class="btn btn-outline-secondary" for="view-tree"><i class="fa-solid fa-folder-tree"></i></label>
</div>
<button class="btn btn-sm btn-primary ms-1 shadow-sm" onclick="openAddModal()"> <button class="btn btn-sm btn-primary ms-1 shadow-sm" onclick="openAddModal()">
<i class="fas fa-plus"></i> Add Resource <i class="fas fa-plus"></i> Add Resource
</button> </button>
@@ -49,7 +43,12 @@
{{{indentHtml}}} {{{indentHtml}}}
<span class="badge bg-secondary">{{kind}}{{#metadata.subType}} ({{metadata.subType}}){{/metadata.subType}}</span> <span class="badge bg-secondary">{{kind}}{{#metadata.subType}} ({{metadata.subType}}){{/metadata.subType}}</span>
</td> </td>
<td><strong>{{name}}</strong><br><small class="text-muted">{{slug}}</small></td> <td>
<a href="#" class="text-reset text-decoration-none" onclick="openEditModal('{{id}}'); return false;" title="View details">
<strong>{{name}}</strong>
</a>
<br><small class="text-muted">{{slug}}</small>
</td>
<td> <td>
{{#metadata.isProduction}}<span class="badge bg-danger">Prod</span>{{/metadata.isProduction}} {{#metadata.isProduction}}<span class="badge bg-danger">Prod</span>{{/metadata.isProduction}}
{{^metadata.isProduction}}<span class="badge bg-info">Dev</span>{{/metadata.isProduction}} {{^metadata.isProduction}}<span class="badge bg-info">Dev</span>{{/metadata.isProduction}}
@@ -376,8 +375,7 @@
function renderTable() { function renderTable() {
const filter = $('#search-filter').val().toLowerCase(); const filter = $('#search-filter').val().toLowerCase();
const sort = $('#sort-by').val(); const sort = $('#sort-by').val();
const viewMode = $('input[name="viewMode"]:checked').val();
let filtered = rawResources.filter(r => { let filtered = rawResources.filter(r => {
if (!filter) return true; if (!filter) return true;
return (r.name || '').toLowerCase().includes(filter) || return (r.name || '').toLowerCase().includes(filter) ||
@@ -402,42 +400,38 @@
let finalRenderList = []; let finalRenderList = [];
if (viewMode === 'tree') { const map = {};
const map = {}; const roots = [];
const roots = []; filtered.forEach(r => { map[r.id] = { ...r, children: [] }; });
filtered.forEach(r => { map[r.id] = { ...r, children: [] }; });
filtered.forEach(r => {
filtered.forEach(r => { const node = map[r.id];
const node = map[r.id]; if (node.parentId && map[node.parentId]) {
if (node.parentId && map[node.parentId]) { map[node.parentId].children.push(node);
map[node.parentId].children.push(node); } else {
} else { roots.push(node);
roots.push(node); }
} });
});
const flatten = (nodes, depth) => {
const flatten = (nodes, depth) => { nodes.forEach(n => {
nodes.forEach(n => { let indentHtml = '';
let indentHtml = ''; for(let i = 0; i < depth; i++) {
for(let i = 0; i < depth; i++) { indentHtml += '<span style="display:inline-block; width: 1.5rem;"></span>';
indentHtml += '<span style="display:inline-block; width: 1.5rem;"></span>'; }
} if (depth > 0) {
if (depth > 0) { indentHtml += '<i class="fa-solid fa-turn-up fa-rotate-90 text-muted me-2"></i>';
indentHtml += '<i class="fa-solid fa-turn-up fa-rotate-90 text-muted me-2"></i>'; }
} n.indentHtml = indentHtml;
n.indentHtml = indentHtml; finalRenderList.push(n);
finalRenderList.push(n); if (n.children.length > 0) {
if (n.children.length > 0) { flatten(n.children, depth + 1);
flatten(n.children, depth + 1); }
} });
}); };
};
flatten(roots, 0);
flatten(roots, 0);
} else {
finalRenderList = filtered.map(r => ({ ...r, indentHtml: '' }));
}
$.scope.resources.empty(); $.scope.resources.empty();
for (const r of finalRenderList) { for (const r of finalRenderList) {
$.scope.resources.push(r); $.scope.resources.push(r);