filtering mesh message types and nodes

This commit is contained in:
Gwendolyn 2024-03-31 15:41:28 +02:00
parent 78fe28b3ec
commit 82d1f48685
3 changed files with 95 additions and 12 deletions

View file

@ -0,0 +1,38 @@
(function () {
function filterOption(option, value) {
if (value === '' || option.text.toLowerCase().includes(value)) {
option.style.display = '';
return true;
} else {
option.style.display = 'none';
return false;
}
}
function performSearch(select, value) {
value = value.toLowerCase().trim();
for (const child of select.children) {
if (child.nodeName === 'OPTGROUP') {
let any_visible = false;
for (const option of child.children) {
if (option.nodeName !== 'OPTION') continue;
any_visible |= filterOption(option, value);
}
if (!any_visible) {
child.style.display = 'none';
} else {
child.style.display = '';
}
} else if (child.nodeName === 'OPTION') {
filterOption(child, value);
}
}
}
function SearchableSelect(select, search) {
search.addEventListener('input', e => performSearch(select, search.value));
performSearch(select, search.value);
}
window.SearchableSelect = SearchableSelect;
})();

View file

@ -1,4 +1,5 @@
{% extends 'mesh/base.html' %}
{% load static %}
{% load i18n %}
{% block heading %}
@ -14,11 +15,28 @@
{% endblock %}
{% block subcontent %}
<style>
#id_recipients {
width: 100%;
}
</style>
<form method="POST" style="max-width:400px;">
{% csrf_token %}
{{ form.as_div }}
{{ form.conditionals | json_script:"form-conditionals" }}
<noscript><input type="hidden" name="noscript" value="1"></noscript>
<script type="text/javascript" src="{% static 'mesh/js/searchable-select.js' %}"></script>
<script type="text/javascript">
(function () {
const select = document.getElementById('id_recipients');
const searchInput = document.createElement('input');
searchInput.type = 'text';
select.parentElement.insertBefore(searchInput, select);
SearchableSelect(select, searchInput);
})();
</script>
<script>
var form_conditionals = JSON.parse(document.getElementById('form-conditionals').innerHTML)
function update_form() {

View file

@ -1,9 +1,19 @@
{% extends 'mesh/base.html' %}
{% load static %}
{% load i18n mesh_node %}
{% block heading %}{% trans 'Mesh messages' %}{% endblock %}
{% block subcontent %}
<style>
.mesh-message-filter .field > select[multiple] {
width: 100%;
}
.mesh-message-filter .field > input.mesh-message-search {
margin-bottom: 2px;
}
</style>
<div class="columns">
<div>
<h4>Send messages</h4>
@ -25,11 +35,15 @@
</div>
<form>
<h4>Filter</h4>
<div class="fields">
<div class="fields mesh-message-filter">
<div class="field">
<input type="text" placeholder="search" class="mesh-message-search" id="mesh-message-type-search"
aria-label="search message types"/>
{{ form.message_types }}
</div>
<div class="field">
<input type="text" placeholder="search" class="mesh-message-search" id="mesh-message-node-search"
aria-label="search nodes"/>
{{ form.src_nodes }}
</div>
<div class="field">
@ -37,6 +51,15 @@
</div>
</div>
</form>
<script type="text/javascript" src="{% static 'mesh/js/searchable-select.js' %}"></script>
<script type="text/javascript">
(function () {
const typeSearch = document.getElementById('mesh-message-type-search');
const nodeSearch = document.getElementById('mesh-message-node-search');
SearchableSelect(typeSearch.nextElementSibling, typeSearch);
SearchableSelect(nodeSearch.nextElementSibling, nodeSearch);
})();
</script>
{% include 'control/fragment_pagination.html' %}
@ -68,25 +91,28 @@
<strong>Minor:</strong> {{ msg.parsed.content.minor }}
{% elif msg.message_type == "CONFIG_HARDWARE" %}
<strong>Chip:</strong> {{ msg.parsed.content.chip.pretty_name }} rev{{ msg.parsed.content.revision_major }}.{{ msg.parsed.content.revision_minor }}
<strong>Chip:</strong> {{ msg.parsed.content.chip.pretty_name }} rev
{{ msg.parsed.content.revision_major }}.{{ msg.parsed.content.revision_minor }}
{% elif msg.message_type == "CONFIG_BOARD" %}
<strong>Board:</strong> {{ msg.parsed.content.board_config.board.pretty_name }}
{% if msg.parsed.content.led %}
<br>
<strong>Status LED:</strong> {{ msg.parsed.content.led }}
<br>
<strong>Status LED:</strong> {{ msg.parsed.content.led }}
{% endif %}
{% if msg.parsed.content.uwb %}
<br>
<strong>UWB:</strong> {{ msg.parsed.content.led }}
<br>
<strong>UWB:</strong> {{ msg.parsed.content.led }}
{% endif %}
{% elif msg.message_type == "CONFIG_FIRMWARE" %}
<strong>Firmware:</strong> {{ msg.parsed.content.app_desc.project_name }} {{ msg.parsed.content.app_desc.version }} (IDF {{ msg.parsed.content.app_desc.idf_version }})
<strong>Firmware:</strong> {{ msg.parsed.content.app_desc.project_name }}
{{ msg.parsed.content.app_desc.version }} (IDF {{ msg.parsed.content.app_desc.idf_version }})
<br>
<strong>Compile Date:</strong> {{ msg.parsed.content.app_desc.compile_date }} {{ msg.parsed.content.app_desc.compile_time }}
<strong>Compile Date:</strong> {{ msg.parsed.content.app_desc.compile_date }}
{{ msg.parsed.content.app_desc.compile_time }}
<br>
<strong>SHA256:</strong> <small>{{ msg.parsed.content.app_desc.app_elf_sha256 }}</small>
@ -103,7 +129,8 @@
<strong>LED config:</strong> {{ msg.parsed.led_config }}
{% elif msg.message_type == "CONFIG_POSITION" %}
<strong>X=</strong>{{ msg.parsed.content.x_pos }}, <strong>Y=</strong>{{ msg.parsed.content.y_pos }}, <strong>Z=</strong>{{ msg.parsed.content.z_pos }}
<strong>X=</strong>{{ msg.parsed.content.x_pos }}, <strong>Y=</strong>
{{ msg.parsed.content.y_pos }}, <strong>Z=</strong>{{ msg.parsed.content.z_pos }}
{% elif msg.message_type == "MESH_ADD_DESTINATIONS" or msg.message_type == "MESH_REMOVE_DESTINATIONS" %}
<strong>adresses:</strong><br>
@ -171,9 +198,9 @@
{% else %}
{% for key, value in msg.data.items %}
{% if key != "src" and key != "dst" and key != "msg_type" %}
<div class="mesh-msg-data mesh-msg-type-{{ key }}">
<strong>{{ key }}</strong>: {{ value }}
</div>
<div class="mesh-msg-data mesh-msg-type-{{ key }}">
<strong>{{ key }}</strong>: {{ value }}
</div>
{% endif %}
{% endfor %}
{% endif %}