8000 feature #53885 [WebProfilerBundle] Allow to search inside profiler ta… · symfony/symfony@0d38e79 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0d38e79

Browse files
committed
feature #53885 [WebProfilerBundle] Allow to search inside profiler tables (javiereguiluz)
This PR was squashed before being merged into the 7.1 branch. Discussion ---------- [WebProfilerBundle] Allow to search inside profiler tables | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | - | License | MIT In the profiler, sometimes tables are very long and it's hard to find things in all those rows. This PR injects a `<input type="search">` field in all tables to have a real-time filter on table contents: ![image](https://github.com/symfony/symfony/assets/73419/fac07bc4-035f-4521-bd87-8893d832c28a) In action it looks like this: ![profiler-table-filter](https://github.com/symfony/symfony/assets/73419/e42f6ad5-d2ff-478e-a006-8f6bff9d8f2b) Commits ------- 36f3c37 [WebProfilerBundle] Allow to search inside profiler tables
2 parents 31b6a56 + 36f3c37 commit 0d38e79

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/bag.html.twig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<div class="table-with-search-field">
12
<table class="{{ class|default('') }}">
23
<thead>
34
<tr>
@@ -18,3 +19,4 @@
1819
{% endfor %}
1920
</tbody>
2021
</table>
22+
</div>

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
class SymfonyProfiler {
1313
constructor() {
1414
this.#createTabs();
15+
this.#createTableSearchFields();
1516
this.#createToggles();
1617
this.#createCopyToClipboard();
1718
this.#convertDateTimesToUserTimezone();
@@ -105,6 +106,56 @@
105106
});
106107
}
107108
109+
#createTableSearchFields() {
110+
document.querySelectorAll('div.table-with-search-field').forEach((tableWrapper, i) => {
111+
const searchField = document.createElement('input');
112+
searchField.type = 'search';
113+
searchField.placeholder = 'search...';
114+
searchField.id = `table-search-field-${i}`;
115+
searchField.classList.add(`table-search-field-input`);
116+
searchField.autocapitalize = 'off';
117+
searchField.autocomplete = 'off';
118+
searchField.autocorrect = 'off';
119+
tableWrapper.insertBefore(searchField, tableWrapper.firstChild);
120+
121+
const labelField = document.createElement('label');
122+
labelField.htmlFor = `table-search-field-${i}`;
123+
labelField.classList.add(`table-search-field-label`);
124+
labelField.textContent = 'Search inside the contents of the table';
125+
tableWrapper.insertBefore(labelField, tableWrapper.firstChild);
126+
127+
searchField.addEventListener('input', () => {
128+
const query = searchField.value.toLowerCase();
129+
let allRowsAreHidden = true;
130+
tableWrapper.querySelectorAll('tbody tr').forEach((row) => {
131+
const rowMatchesQuery = row.textContent.toLowerCase().includes(query);
132+
row.style.display = rowMatchesQuery ? '' : 'none';
133+
134+
if (rowMatchesQuery) {
135+
allRowsAreHidden = false;
136+
}
137+
});
138+
139+
/* if there are no results and all rows are hidden, show a message to avoid confusion */
140+
const noResultsElement = tableWrapper.querySelector('.no-results-message');
141+
if (allRowsAreHidden) {
142+
if (null === noResultsElement) {
143+
const noResultsElement = document.createElement('p');
144+
noResultsElement.textContent = 'No results found.';
145+
noResultsElement.classList.add('no-results-message');
146+
tableWrapper.appendChild(noResultsElement);
147+
} else {
148+
noResultsElement.style.display = '';
149+
}
150+
} else {
151+
if (null !== noResultsElement) {
152+
noResultsElement.style.display = 'none';
153+
}
154+
}
155+
});
156+
});
157+
}
158+
108159
#createToggles() {
109160
const toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])');
110161
toggles.forEach((toggle) => {

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,29 @@ table tbody td.num-col {
614614
text-align: center;
615615
}
616616

617+
div.table-with-search-field {
618+
position: relative;
619+
}
620+
div.table-with-search-field label.table-search-field-label {
621+
display: none;
622+
}
623+
div.table-with-search-field input.table-search-field-input {
624+
position: absolute;
625+
right: 5px;
626+
top: 5px;
627+
max-height: 27px; /* needed for Safari */
628+
}
629+
div.table-with-search-field .no-results-message {
630+
background: var(--page-background);
631+
border: solid var(--table-border-color);
632+
border-width: 0 1px 1px;
633+
border-bottom-left-radius: 6px;
634+
border-bottom-right-radius: 6px;
635+
font-size: var(--table-font-size);
636+
margin-top: -1em;
637+
padding: 15px 10px;
638+
}
639+
617640
{# Utility classes
618641
========================================================================= #}
619642
.block {

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/table.html.twig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<div class="table-with-search-field">
12
<table class="{{ class|default('') }}">
23
<thead>
34
<tr>
@@ -14,3 +15,4 @@
1415
{% endfor %}
1516
</tbody>
1617
</table>
18+
</div>

0 commit comments

Comments
 (0)
0