Improve searching for tabs UI.

Content / filename search is now a regex.
Use .toLocaleString() for loading / baking stats
This commit is contained in:
j433866 2019-05-30 13:28:45 +01:00
parent 9b2f44efb1
commit d94a431537
7 changed files with 250 additions and 112 deletions

View File

@ -284,6 +284,9 @@ class InputWaiter {
case "displayTabSearchResults": case "displayTabSearchResults":
this.displayTabSearchResults(r.data); this.displayTabSearchResults(r.data);
break; break;
case "filterTabError":
this.app.handleError(r.data);
break;
case "setUrl": case "setUrl":
this.setUrl(r.data); this.setUrl(r.data);
break; break;
@ -886,20 +889,20 @@ class InputWaiter {
const loaded = loadedData.loaded; const loaded = loadedData.loaded;
const total = loadedData.total; const total = loadedData.total;
let width = total.toString().length; let width = total.toLocaleString().length;
width = width < 2 ? 2 : width; width = width < 2 ? 2 : width;
const totalStr = total.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const totalStr = total.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
let msg = "Total: " + totalStr; let msg = "Total: " + totalStr;
const loadedStr = loaded.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const loadedStr = loaded.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
msg += "<br>Loaded: " + loadedStr; msg += "<br>Loaded: " + loadedStr;
if (pending > 0) { if (pending > 0) {
const pendingStr = pending.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const pendingStr = pending.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
msg += "<br>Pending: " + pendingStr; msg += "<br>Pending: " + pendingStr;
} else if (loading > 0) { } else if (loading > 0) {
const loadingStr = loading.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const loadingStr = loading.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
msg += "<br>Loading: " + loadingStr; msg += "<br>Loading: " + loadingStr;
} }
@ -1377,8 +1380,8 @@ class InputWaiter {
const showLoading = document.getElementById("input-show-loading").checked; const showLoading = document.getElementById("input-show-loading").checked;
const showLoaded = document.getElementById("input-show-loaded").checked; const showLoaded = document.getElementById("input-show-loaded").checked;
const fileNameFilter = document.getElementById("input-filename-filter").value; const filter = document.getElementById("input-filter").value;
const contentFilter = document.getElementById("input-content-filter").value; const filterType = document.getElementById("input-filter-button").innerText;
const numResults = parseInt(document.getElementById("input-num-results").value, 10); const numResults = parseInt(document.getElementById("input-num-results").value, 10);
this.inputWorker.postMessage({ this.inputWorker.postMessage({
@ -1387,13 +1390,23 @@ class InputWaiter {
showPending: showPending, showPending: showPending,
showLoading: showLoading, showLoading: showLoading,
showLoaded: showLoaded, showLoaded: showLoaded,
fileNameFilter: fileNameFilter, filter: filter,
contentFilter: contentFilter, filterType: filterType,
numResults: numResults numResults: numResults
} }
}); });
} }
/**
* Handle when an option in the filter drop down box is clicked
*
* @param {event} mouseEvent
*/
filterOptionClick(mouseEvent) {
document.getElementById("input-filter-button").innerText = mouseEvent.target.innerText;
this.filterTabSearch();
}
/** /**
* Displays the results of a tab search in the find tab box * Displays the results of a tab search in the find tab box
* *

View File

@ -908,17 +908,26 @@ self.updateMaxTabs = function(maxTabs, activeTab) {
* @param {boolean} searchData.showPending - If true, include pending inputs in the results * @param {boolean} searchData.showPending - If true, include pending inputs in the results
* @param {boolean} searchData.showLoading - If true, include loading inputs in the results * @param {boolean} searchData.showLoading - If true, include loading inputs in the results
* @param {boolean} searchData.showLoaded - If true, include loaded inputs in the results * @param {boolean} searchData.showLoaded - If true, include loaded inputs in the results
* @param {string} searchData.fileNameFilter - A string that must be present in the filename of an input * @param {string} searchData.filter - A regular expression to match the inputs on
* @param {string} searchData.contentFilter - A string that must be present in the input contents * @param {string} searchData.filterType - Either "CONTENT" or "FILENAME". Detemines what should be matched with filter
* @param {number} searchData.numResults - The maximum number of results to be returned * @param {number} searchData.numResults - The maximum number of results to be returned
*/ */
self.filterTabs = function(searchData) { self.filterTabs = function(searchData) {
const showPending = searchData.showPending; const showPending = searchData.showPending,
const showLoading = searchData.showLoading; showLoading = searchData.showLoading,
const showLoaded = searchData.showLoaded; showLoaded = searchData.showLoaded,
filterType = searchData.filterType;
const fileNameFilter = searchData.fileNameFilter; let filterExp;
const contentFilter = searchData.contentFilter; try {
filterExp = new RegExp(searchData.filter, "i");
} catch (error) {
self.postMessage({
action: "filterTabError",
data: error.message
});
return;
}
const numResults = searchData.numResults; const numResults = searchData.numResults;
const inputs = []; const inputs = [];
@ -930,17 +939,28 @@ self.filterTabs = function(searchData) {
if (self.inputs[iNum].status === "pending" && showPending || if (self.inputs[iNum].status === "pending" && showPending ||
self.inputs[iNum].status === "loading" && showLoading || self.inputs[iNum].status === "loading" && showLoading ||
self.inputs[iNum].status === "loaded" && showLoaded) { self.inputs[iNum].status === "loaded" && showLoaded) {
if (typeof self.inputs[iNum].data === "string") { try {
if (self.inputs[iNum].data.slice(0, 4096).toLowerCase().includes(contentFilter)) { if (typeof self.inputs[iNum].data === "string") {
textDisplay = self.inputs[iNum].data.slice(0, 4096); if (filterType.toLowerCase() === "content" &&
addInput = true; filterExp.test(self.inputs[iNum].data.slice(0, 4096))) {
} textDisplay = self.inputs[iNum].data.slice(0, 4096);
} else { addInput = true;
if (self.inputs[iNum].data.name.toLowerCase().includes(fileNameFilter) && }
Utils.arrayBufferToStr(self.inputs[iNum].data.fileBuffer.slice(0, 4096)).toLowerCase().includes(contentFilter)) { } else {
textDisplay = self.inputs[iNum].data.name; if ((filterType.toLowerCase() === "filename" &&
addInput = true; filterExp.test(self.inputs[iNum].data.name)) ||
filterType.toLowerCase() === "content" &&
filterExp.test(Utils.arrayBufferToStr(self.inputs[iNum].data.fileBuffer.slice(0, 4096)))) {
textDisplay = self.inputs[iNum].data.name;
addInput = true;
}
} }
} catch (error) {
self.postMessage({
action: "filterTabError",
data: error.message
});
return;
} }
} }

View File

@ -166,10 +166,9 @@ class Manager {
document.getElementById("input-show-pending").addEventListener("change", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-show-pending").addEventListener("change", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-show-loading").addEventListener("change", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-show-loading").addEventListener("change", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-show-loaded").addEventListener("change", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-show-loaded").addEventListener("change", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-filename-filter").addEventListener("change", this.input.filterTabSearch.bind(this.input)); this.addListeners("#input-filter-content,#input-filter-filename", "click", this.input.filterOptionClick, this.input);
document.getElementById("input-filename-filter").addEventListener("keyup", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-filter").addEventListener("change", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-content-filter").addEventListener("change", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-filter").addEventListener("keyup", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-content-filter").addEventListener("keyup", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-num-results").addEventListener("change", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-num-results").addEventListener("change", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-num-results").addEventListener("keyup", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-num-results").addEventListener("keyup", this.input.filterTabSearch.bind(this.input));
document.getElementById("input-filter-refresh").addEventListener("click", this.input.filterTabSearch.bind(this.input)); document.getElementById("input-filter-refresh").addEventListener("click", this.input.filterTabSearch.bind(this.input));

View File

@ -705,6 +705,28 @@ class OutputWaiter {
} }
const newOutputs = this.getNearbyNums(inputNum, direction); const newOutputs = this.getNearbyNums(inputNum, direction);
const tabsLeft = (newOutputs[0] !== this.getSmallestInputNum());
const tabsRight = (newOutputs[newOutputs.length - 1] !== this.getLargestInputNum());
const firstTabElement = document.getElementById("output-tabs").firstElementChild;
const lastTabElement = document.getElementById("output-tabs").lastElementChild;
if (firstTabElement) {
if (tabsLeft) {
firstTabElement.style.boxShadow = "15px 0px 15px -15px var(--primary-border-colour) inset";
} else {
firstTabElement.style.boxShadow = "";
}
}
if (lastTabElement) {
if (tabsRight) {
lastTabElement.style.boxShadow = "-15px 0px 15px -15px var(--primary-border-colour) inset";
} else {
lastTabElement.style.boxShadow = "";
}
}
for (let i = 0; i < newOutputs.length; i++) { for (let i = 0; i < newOutputs.length; i++) {
tabs.item(i).setAttribute("inputNum", newOutputs[i].toString()); tabs.item(i).setAttribute("inputNum", newOutputs[i].toString());
this.displayTabInfo(newOutputs[i]); this.displayTabInfo(newOutputs[i]);
@ -908,6 +930,27 @@ class OutputWaiter {
this.displayTabInfo(newInputs[i]); this.displayTabInfo(newInputs[i]);
} }
const tabsLeft = (newInputs[0] !== this.getSmallestInputNum());
const tabsRight = (newInputs[newInputs.length - 1] !== this.getLargestInputNum());
const firstTabElement = document.getElementById("output-tabs").firstElementChild;
const lastTabElement = document.getElementById("output-tabs").lastElementChild;
if (firstTabElement) {
if (tabsLeft) {
firstTabElement.style.boxShadow = "15px 0px 15px -15px var(--primary-border-colour) inset";
} else {
firstTabElement.style.boxShadow = "";
}
}
if (lastTabElement) {
if (tabsRight) {
lastTabElement.style.boxShadow = "-15px 0px 15px -15px var(--primary-border-colour) inset";
} else {
lastTabElement.style.boxShadow = "";
}
}
if (newInputs.length > 1) { if (newInputs.length > 1) {
tabsList.parentElement.style.display = "block"; tabsList.parentElement.style.display = "block";
@ -1320,6 +1363,14 @@ class OutputWaiter {
inputNums = Object.keys(this.outputs), inputNums = Object.keys(this.outputs),
results = []; results = [];
let contentFilterExp;
try {
contentFilterExp = new RegExp(contentFilter, "i");
} catch (error) {
this.app.handleError(error);
return;
}
// Search through the outputs for matching output results // Search through the outputs for matching output results
for (let i = 0; i < inputNums.length; i++) { for (let i = 0; i < inputNums.length; i++) {
const iNum = inputNums[i], const iNum = inputNums[i],
@ -1347,7 +1398,7 @@ class OutputWaiter {
data = Utils.arrayBufferToStr(data); data = Utils.arrayBufferToStr(data);
} }
data = data.replace(/[\r\n]/g, ""); data = data.replace(/[\r\n]/g, "");
if (data.toLowerCase().includes(contentFilter)) { if (contentFilterExp.test(data)) {
results.push({ results.push({
inputNum: iNum, inputNum: iNum,
textDisplay: data.slice(0, 100) textDisplay: data.slice(0, 100)
@ -1359,7 +1410,7 @@ class OutputWaiter {
data = Utils.arrayBufferToStr(data); data = Utils.arrayBufferToStr(data);
} }
data = data.replace(/[\r\n]/g, ""); data = data.replace(/[\r\n]/g, "");
if (data.toLowerCase().includes(contentFilter)) { if (contentFilterExp.test(data)) {
results.push({ results.push({
inputNum: iNum, inputNum: iNum,
textDisplay: data.slice(0, 100) textDisplay: data.slice(0, 100)

View File

@ -626,13 +626,13 @@ class WorkerWaiter {
} }
const bakeInfo = document.getElementById("bake-info"); const bakeInfo = document.getElementById("bake-info");
let width = progress.total.toString().length; let width = progress.total.toLocaleString().length;
width = width < 2 ? 2 : width; width = width < 2 ? 2 : width;
const totalStr = progress.total.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const totalStr = progress.total.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
const bakedStr = progress.baked.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const bakedStr = progress.baked.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
const pendingStr = progress.pending.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const pendingStr = progress.pending.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
const bakingStr = progress.baking.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const bakingStr = progress.baking.toLocaleString().padStart(width, " ").replace(/ /g, "&nbsp;");
let msg = "Total: " + totalStr; let msg = "Total: " + totalStr;
msg += "<br>Baked: " + bakedStr; msg += "<br>Baked: " + bakedStr;

View File

@ -768,38 +768,44 @@
</div> </div>
<div class="modal-body" id="input-tab-body"> <div class="modal-body" id="input-tab-body">
<h6>Load Status</h6> <h6>Load Status</h6>
<ul id="input-find-options"> <div id="input-find-options">
<li class="checkbox input-find-option"> <ul id="input-find-options-checkboxes">
<label for="input-show-pending"> <li class="checkbox input-find-option">
<input type="checkbox" id="input-show-pending" checked=""> <label for="input-show-pending">
Pending <input type="checkbox" id="input-show-pending" checked="">
</label> Pending
</li> </label>
<li class="checkbox input-find-option"> </li>
<label for="input-show-loading"> <li class="checkbox input-find-option">
<input type="checkbox" id="input-show-loading" checked=""> <label for="input-show-loading">
Loading <input type="checkbox" id="input-show-loading" checked="">
</label> Loading
</li> </label>
<li class="checkbox input-find-option"> </li>
<label for="input-show-loaded"> <li class="checkbox input-find-option">
<input type="checkbox" id="input-show-loaded" checked=""> <label for="input-show-loaded">
Loaded <input type="checkbox" id="input-show-loaded" checked="">
</label> Loaded
</li> </label>
</ul> </li>
<br> </ul>
<div class="form-group input-find-option"> <div class="form-group input-find-option" id="input-num-results-container">
<label for="input-filename-filter" class="bmd-label-floating">Filename</label> <label for="input-num-results" class="bmd-label-floating">Number of results</label>
<input type="text" class="form-control" id="input-filename-filter"> <input type="number" class="form-control" id="input-num-results" value="20" min="1">
</div>
</div> </div>
<div class="form-group input-find-option"> <div class="form-group input-group">
<label for="input-content-filter" class="bmd-label-floating">Content</label> <div class="toggle-string">
<input type="text" class="form-control" id="input-content-filter"> <label for="input-filter" class="bmd-label-floating toggle-string">Filter (regex)</label>
</div> <input type="text" class="form-control toggle-string" id="input-filter">
<div class="form-group input-find-option"> </div>
<label for="input-num-results" class="bmd-label-floating">Number of results</label> <div class="input-group-append">
<input type="number" class="form-control" id="input-num-results" value="20"> <button class="btn btn-secondary dropdown-toggle" id="input-filter-button" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">CONTENT</button>
<div class="dropdown-menu toggle-dropdown">
<a class="dropdown-item" id="input-filter-content">Content</a>
<a class="dropdown-item" id="input-filter-filename">Filename</a>
</div>
</div>
</div> </div>
<br> <br>
<h6>Results</h6> <h6>Results</h6>
@ -821,46 +827,47 @@
</div> </div>
<div class="modal-body" id="output-tab-body"> <div class="modal-body" id="output-tab-body">
<h6>Bake Status</h6> <h6>Bake Status</h6>
<ul id="output-find-options"> <div id="output-find-options">
<li class="checkbox output-find-option"> <ul id="output-find-options-checkboxes">
<label for="output-show-pending"> <li class="checkbox output-find-option">
<input type="checkbox" id="output-show-pending" checked=""> <label for="output-show-pending">
Pending <input type="checkbox" id="output-show-pending" checked="">
</label> Pending
</li> </label>
<li class="checkbox output-find-option"> </li>
<label for="output-show-baking"> <li class="checkbox output-find-option">
<input type="checkbox" id="output-show-baking" checked=""> <label for="output-show-baking">
Baking <input type="checkbox" id="output-show-baking" checked="">
</label> Baking
</li> </label>
<li class="checkbox output-find-option"> </li>
<label for="output-show-baked"> <li class="checkbox output-find-option">
<input type="checkbox" id="output-show-baked" checked=""> <label for="output-show-baked">
Baked <input type="checkbox" id="output-show-baked" checked="">
</label> Baked
</li> </label>
<li class="checkbox output-find-option"> </li>
<label for="output-show-stale"> <li class="checkbox output-find-option">
<input type="checkbox" id="output-show-stale" checked=""> <label for="output-show-stale">
Stale <input type="checkbox" id="output-show-stale" checked="">
</label> Stale
</li> </label>
<li class="checkbox output-find-option"> </li>
<label for="output-show-errored"> <li class="checkbox output-find-option">
<input type="checkbox" id="output-show-errored" checked=""> <label for="output-show-errored">
Errored <input type="checkbox" id="output-show-errored" checked="">
</label> Errored
</li> </label>
</ul> </li>
<br> </ul>
<div class="form-group output-find-option"> <div class="form-group output-find-option">
<label for="output-content-filter" class="bmd-label-floating">Content</label> <label for="output-content-filter" class="bmd-label-floating">Content filter (regex)</label>
<input type="text" class="form-control" id="output-content-filter"> <input type="text" class="form-control" id="output-content-filter">
</div> </div>
<div class="form-group output-find-option"> <div class="form-group output-find-option" id="output-num-results-container">
<label for="output-num-results" class="bmd-label-floating">Number of results</label> <label for="output-num-results" class="bmd-label-floating">Number of results</label>
<input type="number" class="form-control" id="output-num-results" value="20"> <input type="number" class="form-control" id="output-num-results" value="20">
</div>
</div> </div>
<br> <br>
<h6>Results</h6> <h6>Results</h6>

View File

@ -297,19 +297,67 @@
#input-find-options, #input-find-options,
#output-find-options { #output-find-options {
list-style: none; display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%; width: 100%;
} }
#input-find-options li, .form-group.input-find-option {
#output-find-options li { width: 80%;
margin-left: auto;
margin-right: auto;
}
.input-find-option .toggle-string {
width: 70%;
display: inline-block;
}
.input-find-option-append button {
border-top-right-radius: 4px;
background-color: var(--arg-background) !important;
margin: unset;
}
.input-find-option-append button:hover {
filter: brightness(97%);
}
#input-num-results-container {
width: 20%;
float: right;
margin: 0;
}
.form-group.output-find-option {
width: 70%;
float: left;
}
#output-num-results-container {
width: 20%;
float: right;
margin: 0;
margin-left: 10%;
}
#input-find-options-checkboxes,
#output-find-options-checkboxes {
list-style: none;
width: 70%;
margin-top: auto;
margin-bottom: auto;
}
#input-find-options-checkboxes li,
#output-find-options-checkboxes li {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
float: left; float: left;
padding: 10px; padding: 10px;
width: auto; width: auto;
text-align: center; text-align: center;
vertical-align: middle;
} }