Make tag handling much more flexible

This commit is contained in:
Mark Veidemanis 2022-08-09 07:20:30 +01:00
parent 16c03bc19a
commit ae489b1045
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
3 changed files with 95 additions and 87 deletions

View File

@ -1,67 +1,89 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load joinsep %}
{% block content %} {% block content %}
<script src="{% static 'js/chart.js' %}"></script> <script src="{% static 'js/chart.js' %}"></script>
<script> <script>
function addTag(value) { function setupTags() {
var inputTags = document.getElementById('tags'); var inputTags = document.getElementById('tags');
var btiInstance = inputTags.BulmaTagsInput(); new BulmaTagsInput(inputTags);
btiInstance.add(value);
}
function delTag(value) {
var inputTags = document.getElementById('tags');
var btiInstance = inputTags.BulmaTagsInput();
btiInstance.remove(value);
}
function toggleTag(field, value) {
var queryElement = document.getElementById('query');
var tagText = `${field}: ${value}`;
var present = true;
if (present == true) {
var toAppend = ` AND ${field}: "${value}"`;
var toRemove = `${field}: "${value}"`;
var tagText = `${field}: ${value}`;
} else {
var toAppend = ` AND NOT ${field}: "${value}"`;
var toRemove = `NOT ${field}: "${value}"`;
}
if (!queryElement.value.includes(toAppend) && !queryElement.value.includes(toRemove)) {
addTag(tagText);
} else {
delTag(tagText);
}
}
function populateSearch(field, value, fromTag=false) {
var queryElement = document.getElementById('query');
var present = true;
if (present == true) {
var toAppend = ` AND ${field}: "${value}"`;
var toRemove = `${field}: "${value}"`;
var tagText = `${field}: ${value}`;
} else {
var toAppend = ` AND NOT ${field}: "${value}"`;
var toRemove = `NOT ${field}: "${value}"`;
}
if (!queryElement.value.includes(toAppend) && !queryElement.value.includes(toRemove)) {
if (fromTag) { inputTags.BulmaTagsInput().on('before.add', function(item) {
queryElement.value+=toAppend; if (item.includes(": ")) {
var spl = item.split(": ");
} else { } else {
queryElement.value+=toAppend; var spl = item.split(":");
} }
var field = spl[0];
try {
var value = JSON.parse(spl[1]);
} catch {
var value = spl[1];
}
populateSearch(field, value);
return `${field}: ${value}`;
});
inputTags.BulmaTagsInput().on('after.remove', function(item) {
var spl = item.split(": ");
var field = spl[0];
try {
var value = JSON.parse(spl[1]);
} catch {
var value = spl[1].trim();
}
populateSearch(field, value);
});
}
function populateSearch(field, value) {
var queryElement = document.getElementById('query');
var present = true;
if (present == true) {
var combinations = [`${field}: "${value}"`,
`${field}: "${value}"`,
`${field}: ${value}`,
`${field}:${value}`,
`${field}:"${value}"`];
var toAppend = ` AND ${field}: "${value}"`;
// var toRemove = `${field}: "${value}"`;
// var tagText = `${field}: ${value}`;
} else { } else {
if (fromTag) { var combinations = [`NOT ${field}: "${value}"`,
queryElement.value = queryElement.value.replaceAll(toAppend, ""); `NOT ${field}: "${value}"`,
queryElement.value = queryElement.value.replaceAll(toRemove, ""); `NOT ${field}: ${value}`,
} else { `NOT ${field}:${value}`,
} `NOT ${field}:"${value}"`];
// var toAppend = ` AND NOT ${field}: "${value}"`;
// var toRemove = `NOT ${field}: "${value}"`;
} }
var contains = combinations.some(elem => queryElement.value.includes(elem));
if (!contains) {
queryElement.value+=toAppend;
} else {
for (var index in combinations) {
combination = combinations[index];
queryElement.value = queryElement.value.replaceAll("AND "+combination, "");
queryElement.value = queryElement.value.replaceAll(combination, "");
}
// queryElement.value = queryElement.value.replaceAll(toAppend, "");
// queryElement.value = queryElement.value.replaceAll(toRemove, "");
}
// if (!queryElement.value.includes(toAppend) && !queryElement.value.includes(toRemove)) {
// queryElement.value+=toAppend;
// } else {
// queryElement.value = queryElement.value.replaceAll(toAppend, "");
// queryElement.value = queryElement.value.replaceAll(toRemove, "");
// }
if (field == "src") { if (field == "src") {
document.getElementById("source").selectedIndex = 0; document.getElementById("source").selectedIndex = 0;
} }
if (queryElement.value.startsWith(" AND ")) { if (queryElement.value.startsWith(" AND ")) {
queryElement.value = queryElement.value.replace(" AND ", ""); queryElement.value = queryElement.value.replace(" AND ", "");
} }
if (queryElement.value.startsWith("AND ")) {
queryElement.value = queryElement.value.replace("AND ", "");
}
htmx.trigger("#search", "click"); htmx.trigger("#search", "click");
} }
</script> </script>
@ -339,38 +361,9 @@
</form> </form>
</div> </div>
<div class="block"> <div class="block">
<input id="tags" class="input" type="tags" placeholder="Add query" value=""> <input id="tags" class="input" type="tags" placeholder="Add query" value="{{ tags|joinsep:',' }}">
<script> <script>
var inputTags = document.getElementById('tags'); setupTags();
new BulmaTagsInput(inputTags);
{% for tag in tags %}
inputTags.BulmaTagsInput().add("{{ tag|escapejs }}");
{% endfor %}
inputTags.BulmaTagsInput().on('before.add', function(item) {
if (item.includes(": ")) {
var spl = item.split(": ");
} else {
var spl = item.split(":");
}
var field = spl[0];
try {
var value = JSON.parse(spl[1]);
} catch {
var value = spl[1];
}
populateSearch(field, value, fromTag=true);
return `${field}: ${value}`;
});
inputTags.BulmaTagsInput().on('after.remove', function(item) {
var spl = item.split(": ");
var field = spl[0];
try {
var value = JSON.parse(spl[1]);
} catch {
var value = spl[1];
}
populateSearch(field, value, fromTag=true);
});
</script> </script>
</div> </div>
<div class="block"> <div class="block">

View File

@ -1,5 +1,6 @@
{% load static %} {% load static %}
{% load index %} {% load index %}
{% load joinsep %}
{% include 'partials/notify.html' %} {% include 'partials/notify.html' %}
{% if results %} {% if results %}
<div style="display: none" id="jsonData" data-json="{{ data }}"> <div style="display: none" id="jsonData" data-json="{{ data }}">
@ -63,7 +64,7 @@
{% endif %}"> {% endif %}">
<td> <td>
<a class="has-text-link is-underlined" <a class="has-text-link is-underlined"
onclick="toggleTag('src', '{{ item.src|escapejs }}')"> onclick="populateSearch('src', '{{ item.src|escapejs }}')">
{% if item.src == 'irc' %} {% if item.src == 'irc' %}
<span class="icon" data-tooltip="IRC"> <span class="icon" data-tooltip="IRC">
<i class="fa-solid fa-hashtag" aria-hidden="true"></i> <i class="fa-solid fa-hashtag" aria-hidden="true"></i>
@ -77,7 +78,7 @@
</td> </td>
<td> <td>
<a class="has-text-link is-underlined" <a class="has-text-link is-underlined"
onclick="toggleTag('type', '{{ item.type|escapejs }}')"> onclick="populateSearch('type', '{{ item.type|escapejs }}')">
{% if item.type == 'msg' %} {% if item.type == 'msg' %}
<span class="icon" data-tooltip="Message"> <span class="icon" data-tooltip="Message">
<i class="fa-solid fa-message"></i> <i class="fa-solid fa-message"></i>
@ -122,7 +123,7 @@
<td style="max-width: 10em" class="wrap">{{ item.msg }}</td> <td style="max-width: 10em" class="wrap">{{ item.msg }}</td>
<td> <td>
<a class="has-text-link is-underlined" <a class="has-text-link is-underlined"
onclick="toggleTag('host', '{{ item.host|escapejs }}')"> onclick="populateSearch('host', '{{ item.host|escapejs }}')">
{{ item.host }} {{ item.host }}
</a> </a>
</td> </td>
@ -143,7 +144,7 @@
</span> </span>
{% endif %} {% endif %}
</div> </div>
<a class="nowrap-child has-text-link is-underlined" onclick="toggleTag('nick', '{{ item.nick|escapejs }}')"> <a class="nowrap-child has-text-link is-underlined" onclick="populateSearch('nick', '{{ item.nick|escapejs }}')">
{{ item.nick }} {{ item.nick }}
</a> </a>
{% if item.num_chans is not None %} {% if item.num_chans is not None %}
@ -171,7 +172,7 @@
<td> <td>
<div class="nowrap-parent"> <div class="nowrap-parent">
<a class="nowrap-child has-text-link is-underlined" <a class="nowrap-child has-text-link is-underlined"
onclick="toggleTag('channel', '{{ item.channel|escapejs }}')"> onclick="populateSearch('channel', '{{ item.channel|escapejs }}')">
{{ item.channel }} {{ item.channel }}
</a> </a>
{% if item.num_users is not None %} {% if item.num_users is not None %}
@ -185,7 +186,7 @@
</td> </td>
<td> <td>
<a class="has-text-link is-underlined" <a class="has-text-link is-underlined"
onclick="toggleTag('net', '{{ item.net|escapejs }}')"> onclick="populateSearch('net', '{{ item.net|escapejs }}')">
{{ item.net }} {{ item.net }}
</a> </a>
</td> </td>
@ -196,3 +197,16 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{# Update the tags in case the user changed the query #}
{# Check for focus and refocus #}
<script>
var inputTags = document.getElementsByClassName('tags-input');
var inputBox = document.querySelector("[placeholder='Add query']");
var isFocused = (document.activeElement === inputBox);
inputTags[0].outerHTML = '<input id="tags" class="input" type="tags" placeholder="Add query" value="{{ tags|joinsep:',' }}">';
setupTags();
var inputBox = document.querySelector("[placeholder='Add query']");
if (isFocused) {
inputBox.focus();
}
</script>

View File

@ -72,7 +72,8 @@ def create_tags(query):
spl = query.split("AND") spl = query.split("AND")
spl = [x.strip() for x in spl if ":" in x] spl = [x.strip() for x in spl if ":" in x]
spl = [x.replace('"', "") for x in spl] spl = [x.replace('"', "") for x in spl]
return spl tags = [f"{tag}: {elem}" for tag, elem in [x.split(":") for x in spl]]
return tags
def drilldown_search(request): def drilldown_search(request):