Skip to content

Commit 6c286cd

Browse files
authored
Add collapse all and expand level buttons to conan report diff html output (#19240)
* Add collapse all and expand level buttons, UI still needs to be improved * Better UX, hide sidebar too * Have a way to filter by file status, useful for checking new files only for example * Move hide arrow
1 parent f972abd commit 6c286cd

File tree

1 file changed

+181
-11
lines changed

1 file changed

+181
-11
lines changed

conan/cli/formatters/report/diff_html.py

Lines changed: 181 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
</li>
1313
{%- endfor %}
1414
{%- for name, file_info in folder_info["files"].items() %}
15-
<li class="file file-{{ "renamed" if file_info["renamed_to"] else (
16-
"deleted" if file_info["is_deleted"] else (
17-
"new" if file_info["is_new"] else "old")) }}"
18-
data-path="{{ file_info["relative_path"] }}">
15+
{% set file_type = "renamed" if file_info["renamed_to"] else (
16+
"deleted" if file_info["is_deleted"] else (
17+
"new" if file_info["is_new"] else "old")) %}
18+
<li class="file file-{{ file_type }}"
19+
data-path="{{ file_info["relative_path"] }}"
20+
data-type="{{ file_type }}">
1921
<a href="#diff_{{- safe_filename(file_info["filename"]) -}}"
2022
onclick="setDataIsLinked(event)" draggable="false"
2123
class="side-link"
@@ -75,6 +77,7 @@
7577
--folder-summary-hover-bgColor: #e0e0e033;
7678
--folder-ul-hover-borderColor: #00000066;
7779
--sidebar-li-a-hover-bgColor: #e0e0e0;
80+
--sidebar-button-hover-bgColor: var(--sidebar-li-a-hover-bgColor);
7881
--sidebar-link-color: black;
7982
--sidebar-link-hover-color: var(--sidebar-link-color);
8083
--sidebar-link-visited-color: var(--sidebar-link-color);
@@ -144,15 +147,67 @@
144147
padding-top: 5px;
145148
}
146149
150+
.sidebar-reveal {
151+
display: none;
152+
position: sticky;
153+
top: 10px;
154+
}
155+
147156
.search-area {
148157
border-bottom: 1px solid var(--search-area-borderColor);
149158
}
150159
160+
.search-header {
161+
display: flex;
162+
justify-content: space-between;
163+
}
164+
151165
.search-field {
152166
border: 1px solid var(--search-field-borderColor);
153167
border-radius: 5px;
154168
padding: 5px;
155169
margin: 5px;
170+
width: 80%;
171+
}
172+
173+
.file-tree-controls {
174+
border-bottom: 1px solid var(--search-area-borderColor);
175+
padding: 5px;
176+
display: flex;
177+
justify-content: space-between;
178+
align-items: center;
179+
}
180+
181+
.file-tree-controls .folder-collapse button {
182+
display: inline-block;
183+
line-height: 0.7;
184+
}
185+
186+
.file-tree-controls button,
187+
.sidebar-reveal button,
188+
.search-header button {
189+
cursor: pointer;
190+
border: 0px solid var(--search-field-borderColor);
191+
border-radius: 5px;
192+
background: none;
193+
padding: 5px;
194+
min-width: 3ch;
195+
}
196+
197+
.file-tree-controls button:hover,
198+
.sidebar-reveal button:hover,
199+
.search-header button:hover {
200+
background-color: var(--sidebar-li-a-hover-bgColor);
201+
}
202+
203+
.file-tree-more {
204+
display: none;
205+
padding: 5px;
206+
border-bottom: 1px solid var(--search-area-borderColor);
207+
}
208+
209+
.file-tree-more-option {
210+
display: block;
156211
}
157212
158213
.file-list {
@@ -621,13 +676,29 @@
621676
let emptySearch = true;
622677
let includedFiles = 0;
623678
679+
const typeVisibility = {
680+
"renamed": document.getElementById("show-moved-files").checked,
681+
"deleted": document.getElementById("show-deleted-files").checked,
682+
"new": document.getElementById("show-new-files").checked,
683+
"old": document.getElementById("show-old-files").checked,
684+
};
685+
624686
sidebar.forEach(async function(item) {
687+
if (item.dataset.path === undefined) {
688+
// A folder, those are handled later
689+
return;
690+
}
625691
const text = item.dataset.path.toLowerCase();
626692
const shouldInclude = includeSearchQuery === "" || text.includes(includeSearchQuery);
627-
const shouldExclude = excludeSearchQuery !== "" && text.includes(excludeSearchQuery);
693+
let shouldExclude = excludeSearchQuery !== "" && text.includes(excludeSearchQuery);
628694
const associatedId = item.querySelector("a").getAttribute("href").substring(1)
629695
const contentItem = document.getElementById(associatedId);
630696
697+
const fileType = item.dataset.type;
698+
const isTypeVisible = typeVisibility[fileType] !== false;
699+
700+
shouldExclude = shouldExclude || !isTypeVisible;
701+
631702
if (shouldInclude) {
632703
if (shouldExclude) {
633704
item.style.display = "none";
@@ -700,24 +771,123 @@
700771
}
701772
});
702773
}
774+
775+
function toggleFolders(open) {
776+
if (open) {
777+
const toOpen = document.querySelectorAll('details.folder:open > ul > li > details.folder:not(:open)');
778+
if (toOpen.length === 0) {
779+
// We might need to open the root folders
780+
document.querySelectorAll('.file-list > li > details.folder:not(:open)').forEach(d => d.open = true);
781+
} else {
782+
toOpen.forEach(d => d.open = true);
783+
}
784+
} else {
785+
document.querySelectorAll('details.folder:open').forEach(d => d.open = false);
786+
}
787+
}
788+
789+
function toggleSidebar(show) {
790+
const sidebar = document.querySelector('.sidebar');
791+
const sidebarReveal = document.querySelector('.sidebar-reveal');
792+
const content = document.querySelector('.content');
793+
if (show) {
794+
sidebar.style.display = 'block';
795+
sidebarReveal.style.display = 'none';
796+
content.style.padding = '20px';
797+
} else {
798+
sidebar.style.display = 'none';
799+
sidebarReveal.style.display = 'block';
800+
content.style.padding = '20px 20px 20px 5px';
801+
}
802+
}
803+
804+
function toggleMoreFileTree() {
805+
const moreOptions = document.querySelector('.file-tree-more');
806+
console.log(moreOptions.style.display);
807+
const show = moreOptions.style.display !== 'block';
808+
if (show) {
809+
moreOptions.style.display = 'block';
810+
} else {
811+
moreOptions.style.display = 'none';
812+
}
813+
}
703814
</script>
704815
</head>
705816
<body>
706817
<div class='container'>
707818
<div class='sidebar'>
708819
<div id="sidebar-contents">
709820
<div class="search-area">
710-
<input type="search" class="search-field" id="search-include" placeholder="Include search..." oninput="onIncludeSearchInput(event)" />
711-
<input type="search" class="search-field" id="search-exclude" placeholder="Exclude search..." oninput="onExcludeSearchInput(event)" />
712-
<span id="searching_icon" style="display:none">...</span>
821+
<div class="search-header">
822+
<div>
823+
<input type="search" class="search-field" id="search-include" placeholder="Include search..." oninput="onIncludeSearchInput(event)" />
824+
<input type="search" class="search-field" id="search-exclude" placeholder="Exclude search..." oninput="onExcludeSearchInput(event)" />
825+
<span id="searching_icon" style="display:none">...</span>
826+
</div>
827+
828+
<button onclick="toggleSidebar(false)" title="Hide">
829+
&#x2190;
830+
</button>
831+
</div>
713832
<p>Showing <b id="file-count">{{ content|length }}</b> out of <b>{{ content|length }}</b> files</p>
714833
</div>
715-
<ul class="file-list">
716-
{{ render_sidebar_folder("", per_folder) }}
717-
</ul>
834+
<div class="file-tree">
835+
<div class="file-tree-controls">
836+
<div class="folder-collapse">
837+
<button onclick="toggleFolders(true)" title="Expand current level">
838+
&#x02C4;
839+
<br/>
840+
&#x02C5;
841+
</button>
842+
<button onclick="toggleFolders(false)" title="Collapse all">
843+
&#x02C5;
844+
<br/>
845+
&#x02C4
846+
</button>
847+
</div>
848+
<button onclick="toggleMoreFileTree()" title="Show more options"
849+
class="file-tree-reveal-more">
850+
&#x22EE;
851+
</button>
852+
</div>
853+
<div class="file-tree-more">
854+
<h4>Show...</h4>
855+
<div class="file-tree-more-option">
856+
<input type="checkbox" id="show-old-files" checked
857+
onclick="debouncedOnSearchInput(event)"/>
858+
<label for="show-old-files">Old files</label>
859+
</div>
860+
861+
<div class="file-tree-more-option">
862+
<input type="checkbox" id="show-new-files" checked
863+
onclick="debouncedOnSearchInput(event)"/>
864+
<label for="show-new-files">New files</label>
865+
</div>
866+
867+
<div class="file-tree-more-option">
868+
<input type="checkbox" id="show-deleted-files" checked
869+
onclick="debouncedOnSearchInput(event)"/>
870+
<label for="show-deleted-files">Deleted files</label>
871+
</div>
872+
873+
<div class="file-tree-more-option">
874+
<input type="checkbox" id="show-moved-files" checked
875+
onclick="debouncedOnSearchInput(event)"/>
876+
<label for="show-moved-files">Moved files</label>
877+
</div>
878+
</div>
879+
<ul class="file-list">
880+
{{ render_sidebar_folder("", per_folder) }}
881+
</ul>
882+
</div>
718883
</div>
719884
<span id="empty_search" style="display:none">No results found</span>
720885
</div>
886+
<div class='sidebar-reveal'>
887+
<button onclick="toggleSidebar(true)" title="Show">
888+
&#x2192;
889+
</button>
890+
</div>
721891
<div class='content'>
722892
<div class="diff-header">
723893
<h2>Diff Report Between <b class="del">{{ old_reference.repr_notime() }}</b> And <b class="add">{{ new_reference.repr_notime() }}</b></h2>

0 commit comments

Comments
 (0)