Reformat and add blacklisted directories to DjHTML

This commit is contained in:
2022-09-05 07:20:30 +01:00
parent 5be02807e3
commit 958eb2b549
51 changed files with 3115 additions and 3123 deletions

View File

@@ -2,141 +2,141 @@
{% load static %}
{% load joinsep %}
{% block outer_content %}
{% if params.modal == 'context' %}
<div
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_context' %}"
hx-vals='{"net": "{{ params.net|escapejs }}",
"num": "{{ params.num|escapejs }}",
"source": "{{ params.source|escapejs }}",
"channel": "{{ params.channel|escapejs }}",
"time": "{{ params.time|escapejs }}",
"date": "{{ params.date|escapejs }}",
"index": "{{ params.index }}",
"type": "{{ params.type|escapejs }}",
"mtype": "{{ params.mtype|escapejs }}",
"nick": "{{ params.nick|escapejs }}"}'
hx-target="#modals-here"
hx-trigger="load">
</div>
{% if params.modal == 'context' %}
<div
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_context' %}"
hx-vals='{"net": "{{ params.net|escapejs }}",
"num": "{{ params.num|escapejs }}",
"source": "{{ params.source|escapejs }}",
"channel": "{{ params.channel|escapejs }}",
"time": "{{ params.time|escapejs }}",
"date": "{{ params.date|escapejs }}",
"index": "{{ params.index }}",
"type": "{{ params.type|escapejs }}",
"mtype": "{{ params.mtype|escapejs }}",
"nick": "{{ params.nick|escapejs }}"}'
hx-target="#modals-here"
hx-trigger="load">
</div>
{% endif %}
<script src="{% static 'js/chart.js' %}"></script>
<script src="{% static 'tabs.js' %}"></script>
<script>
function setupTags() {
var inputTags = document.getElementById('tags');
new BulmaTagsInput(inputTags);
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];
}
return `${field}: ${value}`;
});
inputTags.BulmaTagsInput().on('after.remove', function(item) {
var spl = item.split(": ");
var field = spl[0];
var value = spl[1].trim();
});
}
function populateSearch(field, value) {
var inputTags = document.getElementById('tags');
inputTags.BulmaTagsInput().add(field+": "+value);
//htmx.trigger("#search", "click");
}
</script>
<div class="grid-stack" id="grid-stack-main">
<div class="grid-stack-item" gs-w="7" gs-h="10" gs-y="0" gs-x="1">
<div class="grid-stack-item-content">
<nav class="panel">
<p class="panel-heading" style="padding: .2em; line-height: .5em;">
<i class="fa-solid fa-arrows-up-down-left-right has-text-grey-light"></i>
Search
</p>
<article class="panel-block is-active">
{% include 'ui/drilldown/search_partial.html' %}
</article>
</nav>
</div>
</div>
</div>
<script>
var grid = GridStack.init({
cellHeight: 20,
cellWidth: 50,
auto: true,
float: true,
draggable: {handle: '.panel-heading', scroll: false, appendTo: 'body'},
removable: false,
});
// GridStack.init();
setupTags();
// a widget is ready to be loaded
document.addEventListener('load-widget', function(event) {
let container = htmx.find('#drilldown-widget');
// get the scripts, they won't be run on the new element so we need to eval them
var scripts = htmx.findAll(container, "script");
let widgetelement = container.firstElementChild.cloneNode(true);
// check if there's an existing element like the one we want to swap
let grid_element = htmx.find('#grid-stack-main');
let existing_widget = htmx.find(grid_element, '#drilldown-widget-results');
// get the size and position attributes
if (existing_widget) {
let attrs = existing_widget.getAttributeNames();
for (let i = 0, len = attrs.length; i < len; i++) {
if (attrs[i].startsWith('gs-')) { // only target gridstack attributes
widgetelement.setAttribute(attrs[i], existing_widget.getAttribute(attrs[i]));
}
}
}
// clear the queue element
container.outerHTML = "";
// temporary workaround, other widgets can be duplicated, but not results
if (widgetelement.id == 'drilldown-widget-results') {
grid.removeWidget("drilldown-widget-{{ unique }}");
}
grid.addWidget(widgetelement);
// re-create the HTMX JS listeners, otherwise HTMX won't work inside the grid
htmx.process(widgetelement);
// run the JS scripts inside the added element again
// for instance, this will fix the dropdown
for (var i = 0; i < scripts.length; i++) {
eval(scripts[i].innerHTML);
}
});
</script>
<div id="modals-here">
</div>
<div id="items-here">
</div>
<div id="widgets-here" style="display: none;">
</div>
<div id="results" style="display: none;">
{% if table %}
{% include 'widgets/table_results.html' %}
{% endif %}
<script src="{% static 'js/chart.js' %}"></script>
<script src="{% static 'tabs.js' %}"></script>
<script>
function setupTags() {
var inputTags = document.getElementById('tags');
new BulmaTagsInput(inputTags);
</div>
<script>
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];
}
return `${field}: ${value}`;
});
inputTags.BulmaTagsInput().on('after.remove', function(item) {
var spl = item.split(": ");
var field = spl[0];
var value = spl[1].trim();
});
}
function populateSearch(field, value) {
var inputTags = document.getElementById('tags');
inputTags.BulmaTagsInput().add(field+": "+value);
//htmx.trigger("#search", "click");
}
</script>
<div class="grid-stack" id="grid-stack-main">
<div class="grid-stack-item" gs-w="7" gs-h="10" gs-y="0" gs-x="1">
<div class="grid-stack-item-content">
<nav class="panel">
<p class="panel-heading" style="padding: .2em; line-height: .5em;">
<i class="fa-solid fa-arrows-up-down-left-right has-text-grey-light"></i>
Search
</p>
<article class="panel-block is-active">
{% include 'ui/drilldown/search_partial.html' %}
</article>
</nav>
</div>
</div>
</div>
<script>
var grid = GridStack.init({
cellHeight: 20,
cellWidth: 50,
auto: true,
float: true,
draggable: {handle: '.panel-heading', scroll: false, appendTo: 'body'},
removable: false,
});
// GridStack.init();
setupTags();
// a widget is ready to be loaded
document.addEventListener('load-widget', function(event) {
let container = htmx.find('#drilldown-widget');
// get the scripts, they won't be run on the new element so we need to eval them
var scripts = htmx.findAll(container, "script");
let widgetelement = container.firstElementChild.cloneNode(true);
// check if there's an existing element like the one we want to swap
let grid_element = htmx.find('#grid-stack-main');
let existing_widget = htmx.find(grid_element, '#drilldown-widget-results');
// get the size and position attributes
if (existing_widget) {
let attrs = existing_widget.getAttributeNames();
for (let i = 0, len = attrs.length; i < len; i++) {
if (attrs[i].startsWith('gs-')) { // only target gridstack attributes
widgetelement.setAttribute(attrs[i], existing_widget.getAttribute(attrs[i]));
}
}
}
// clear the queue element
container.outerHTML = "";
// temporary workaround, other widgets can be duplicated, but not results
if (widgetelement.id == 'drilldown-widget-results') {
grid.removeWidget("drilldown-widget-{{ unique }}");
}
grid.addWidget(widgetelement);
// re-create the HTMX JS listeners, otherwise HTMX won't work inside the grid
htmx.process(widgetelement);
// run the JS scripts inside the added element again
// for instance, this will fix the dropdown
for (var i = 0; i < scripts.length; i++) {
eval(scripts[i].innerHTML);
}
});
</script>
<div id="modals-here">
</div>
<div id="items-here">
</div>
<div id="widgets-here" style="display: none;">
</div>
<div id="results" style="display: none;">
{% if table %}
{% include 'widgets/table_results.html' %}
{% endif %}
</div>
<script>
</script>
</script>
{% endblock %}

View File

@@ -1,401 +1,401 @@
<form class="skipEmptyFields" method="POST" hx-post="{% url 'search' %}"
hx-trigger="change"
hx-target="#results"
hx-swap="innerHTML"
hx-indicator="#spinner">
{% csrf_token %}
<div class="columns">
<div class="column">
<div class="field has-addons">
<div id="query" class="control is-expanded has-icons-left">
<input
hx-post="{% url 'search' %}"
hx-trigger="keyup changed delay:200ms"
hx-target="#results"
hx-swap="innerHTML"
name="query"
value="{{ params.query }}"
class="input"
type="text"
placeholder="Search something">
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</div>
<div class="control">
<div class="field">
<button
id="search"
class="button is-info is-fullwidth"
hx-post="{% url 'search' %}"
hx-trigger="click"
hx-target="#results"
hx-swap="innerHTML">
Search
</button>
</div>
</div>
</div>
</div>
<div class="column is-3">
<div class="nowrap-parent">
<div
data-script="on click toggle .is-hidden on #options"
class="button is-light has-text-link is-right nowrap-child">
Options
</div>
<div class="nowrap-child">
<span id="spinner" class="button is-light has-text-link is-loading htmx-indicator">Static</span>
</div>
</div>
</div>
</div>
<div id="options" class="block is-hidden">
<div class="columns is-multiline">
<div class="column is-narrow">
<div class="field has-addons">
<div class="control has-icons-left">
<span class="select">
<select name="size">
{% for size in sizes %}
{% if size == params.size %}
<option selected value="{{ size }}">{{ size }}</option>
{% else %}
<option value="{{ size }}">{{ size }}</option>
{% endif %}
{% endfor %}
</select>
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</span>
</div>
<p class="control">
<a class="button is-static">
results
</a>
</p>
</div>
</div>
<div class="column is-narrow">
<div class="field has-addons block">
<div class="control has-icons-left">
<span class="select">
<select id="source" name="source">
{% if params.source == 'irc' %}
<option selected value="irc">IRC</option>
{% else %}
<option value="irc">IRC</option>
{% endif %}
{% if params.source == 'dis' %}
<option selected value="dis">Discord</option>
{% else %}
<option value="dis">Discord</option>
{% endif %}
{% if params.source == None %}
<option selected value="4ch">4chan</option>
{% elif params.source == '4ch' %}
<option selected value="4ch">4chan</option>
{% else %}
<option value="4ch">4chan</option>
{% endif %}
{% if params.source == 'all' %}
<option selected value="all">All</option>
{% else %}
<option value="all">All</option>
{% endif %}
</select>
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</span>
</div>
<p class="control">
<a class="button is-static">
source
</a>
</p>
</div>
<div class="control">
<div class="field">
<input
id="dedup_switch"
type="checkbox"
class="switch is-rounded is-info"
name="dedup"
{% if params.dedup == "on" %}
checked="checked"
{% endif %}>
<label
for="dedup_switch">
Deduplicate results
</label>
</div>
</div>
</div>
<div class="column is-narrow">
<div id="sentiment">
<div class="field has-addons">
<div class="control">
<input
{% if params.check_sentiment != "on" %}
disabled="undefined"
{% endif %}
name="sentiment" id="sliderWithValue" class="slider has-output-tooltip is-fullwidth" min="-1" max="1"
{% if params.sentiment == None %}
value="0"
{% else %}
value="{{ params.sentiment }}"
{% endif %}
step="0.05" type="range">
<output for="sliderWithValue" class="slider-output">
{% if params.sentiment == None %}
0
{% else %}
{{ params.sentiment }}
{% endif %}
</output>
<script>bulmaSlider.attach();</script>
</div>
<p class="control">
<a class="button is-static">
sentiment
</a>
</p>
</div>
<div class="control">
<label class="radio button has-text-link">
<input
type="radio"
value="below"
class="sentiment-radio"
{% if params.sentiment_method == 'below' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Below">
<i class="fa-solid fa-face-frown"></i>
</span>
</label>
<label class="radio button has-text-link is-hidden">
<input
type="radio"
value="exact"
class="sentiment-radio"
{% if params.sentiment_method == 'exact' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Exact">
<i class="fa-solid fa-face-smile"></i>
</span>
</label>
<label class="radio button has-text-link">
<input
type="radio"
value="above"
class="sentiment-radio"
{% if params.sentiment_method == 'above' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Above">
<i class="fa-solid fa-face-smile"></i>
</span>
</label>
<label class="radio button has-text-link">
<input
type="radio"
value="nonzero"
class="sentiment-radio"
{% if params.sentiment_method == 'nonzero' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Nonzero">
<i class="fa-solid fa-face-meh-blank"></i>
</span>
</label>
</div>
</div>
<div class="control">
<div class="field">
<input
id="sentiment_switch"
type="checkbox"
class="switch is-rounded is-info"
name="check_sentiment"
data-script="on click toggle @disabled on #sliderWithValue then toggle @disabled on #sentiment then toggle @disabled on .sentiment-radio"
{% if params.check_sentiment == "on" %}
checked
{% endif %}>
<label
for="sentiment_switch">
Check sentiment
</label>
</div>
</div>
<div class="control">
<div class="field">
<input
id="sentiment_graph_switch"
type="checkbox"
class="switch is-rounded is-info"
name="show_sentiment"
data-script="on click toggle .is-hidden on #sentiment-container">
<label
for="sentiment_graph_switch">
Show graph
</label>
</div>
</div>
</div>
<div class="column is-narrow">
<div id="date">
<div class="field">
<div class="control">
<input type="date" name="dates" value="{{ params.date }}">
<script>
var options = {
"type": "datetime",
"isRange": true,
"color": "info",
"validateLabel": "Save",
"dateFormat": "yyyy-MM-dd",
"startDate": "{{ params.from_date|escapejs }}",
"startTime": "{{ params.from_time|escapejs }}",
"endDate": "{{ params.to_date|escapejs }}",
"endTime": "{{ params.to_time|escapejs }}",
"displayMode": "dialog"
};
// Initialize all input of type date
var calendars = bulmaCalendar.attach('[type="date"]', options);
// Loop on each calendar initialized
for(var i = 0; i < calendars.length; i++) {
// Add listener to select event
calendars[i].on('save', date => {
htmx.trigger("#search", "click");
});
}
</script>
</div>
</div>
<div class="control">
<label class="radio button has-text-link">
<input
type="radio"
value="desc"
name="sorting"
{% if params.sorting == None %}
checked
{% elif params.sorting == 'desc' %}
checked
{% endif %}>
<span class="icon" data-tooltip="Sort descending">
<i class="fa-solid fa-sort-down"></i>
</span>
</label>
<label class="radio button">
<input
type="radio"
value="asc"
name="sorting"
{% if params.sorting == 'asc' %}
checked
{% endif %}>
<span class="icon" data-tooltip="Sort ascending">
<i class="fa-solid fa-sort-up"></i>
</span>
</label>
<label class="radio button">
<input
type="radio"
value="none"
name="sorting"
{% if params.sorting == 'none' %}
checked
{% endif %}>
<span class="icon" data-tooltip="No sort">
<i class="fa-solid fa-sort"></i>
</span>
</label>
</div>
</div>
</div>
<div class="column is-narrow rounded-tooltip">
<div class="field has-addons">
<div class="control has-icons-left">
<span class="select is-warning">
<select {% if not user.is_superuser %}disabled{% endif %} id="index" name="index">
{% if params.index == 'main' %}
<option selected value="main">Main</option>
{% elif params.index == None %}
<option selected value="main">Main</option>
{% else %}
<option value="main">Main</option>
{% endif %}
{% if params.index == 'int' %}
<option selected value="int">Internal</option>
{% else %}
<option value="int">Internal</option>
{% endif %}
{% if params.index == 'meta' %}
<option selected value="meta">Meta</option>
{% else %}
<option value="meta">Meta</option>
{% endif %}
</select>
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</span>
</div>
<p class="control">
<a class="button is-static">
index
</a>
</p>
</div>
{% if not user.is_superuser %}
<span class="tooltiptext tag is-danger is-light">No access</span>
{% endif %}
</div>
</div>
</div>
<div class="block">
<input
hx-trigger="change"
hx-trigger="change"
hx-target="#results"
hx-swap="innerHTML"
hx-indicator="#spinner">
{% csrf_token %}
<div class="columns">
<div class="column">
<div class="field has-addons">
<div id="query" class="control is-expanded has-icons-left">
<input
hx-post="{% url 'search' %}"
hx-trigger="keyup changed delay:200ms"
hx-target="#results"
hx-swap="innerHTML"
id="tags"
name="query"
value="{{ params.query }}"
class="input"
type="tags"
name="tags"
placeholder="Tag search: nick: john"
value="{{ params.tags }}">
type="text"
placeholder="Search something">
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</div>
<div class="control">
<div class="field">
<button
id="search"
class="button is-info is-fullwidth"
hx-post="{% url 'search' %}"
hx-trigger="click"
hx-target="#results"
hx-swap="innerHTML">
Search
</button>
</div>
</div>
</div>
</div>
<div class="is-hidden"></div>
<div class="column is-3">
<div class="nowrap-parent">
<div
data-script="on click toggle .is-hidden on #options"
class="button is-light has-text-link is-right nowrap-child">
Options
</div>
<div class="nowrap-child">
<span id="spinner" class="button is-light has-text-link is-loading htmx-indicator">Static</span>
</div>
</div>
</div>
</div>
<div id="options" class="block is-hidden">
<div class="columns is-multiline">
<div class="column is-narrow">
<div class="field has-addons">
<div class="control has-icons-left">
<span class="select">
<select name="size">
{% for size in sizes %}
{% if size == params.size %}
<option selected value="{{ size }}">{{ size }}</option>
{% else %}
<option value="{{ size }}">{{ size }}</option>
{% endif %}
{% endfor %}
</select>
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</span>
</div>
<p class="control">
<a class="button is-static">
results
</a>
</p>
</div>
</div>
<div class="column is-narrow">
<div class="field has-addons block">
<div class="control has-icons-left">
<span class="select">
<select id="source" name="source">
{% if params.source == 'irc' %}
<option selected value="irc">IRC</option>
{% else %}
<option value="irc">IRC</option>
{% endif %}
{% if params.source == 'dis' %}
<option selected value="dis">Discord</option>
{% else %}
<option value="dis">Discord</option>
{% endif %}
{% if params.source == None %}
<option selected value="4ch">4chan</option>
{% elif params.source == '4ch' %}
<option selected value="4ch">4chan</option>
{% else %}
<option value="4ch">4chan</option>
{% endif %}
{% if params.source == 'all' %}
<option selected value="all">All</option>
{% else %}
<option value="all">All</option>
{% endif %}
</select>
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</span>
</div>
<p class="control">
<a class="button is-static">
source
</a>
</p>
</div>
<div class="control">
<div class="field">
<input
id="dedup_switch"
type="checkbox"
class="switch is-rounded is-info"
name="dedup"
{% if params.dedup == "on" %}
checked="checked"
{% endif %}>
<label
for="dedup_switch">
Deduplicate results
</label>
</div>
</div>
</div>
<div class="column is-narrow">
<div id="sentiment">
<div class="field has-addons">
<div class="control">
<input
{% if params.check_sentiment != "on" %}
disabled="undefined"
{% endif %}
name="sentiment" id="sliderWithValue" class="slider has-output-tooltip is-fullwidth" min="-1" max="1"
{% if params.sentiment == None %}
value="0"
{% else %}
value="{{ params.sentiment }}"
{% endif %}
step="0.05" type="range">
<output for="sliderWithValue" class="slider-output">
{% if params.sentiment == None %}
0
{% else %}
{{ params.sentiment }}
{% endif %}
</output>
<script>bulmaSlider.attach();</script>
</div>
<p class="control">
<a class="button is-static">
sentiment
</a>
</p>
</div>
<div class="control">
<label class="radio button has-text-link">
<input
type="radio"
value="below"
class="sentiment-radio"
{% if params.sentiment_method == 'below' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Below">
<i class="fa-solid fa-face-frown"></i>
</span>
</label>
<label class="radio button has-text-link is-hidden">
<input
type="radio"
value="exact"
class="sentiment-radio"
{% if params.sentiment_method == 'exact' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Exact">
<i class="fa-solid fa-face-smile"></i>
</span>
</label>
<label class="radio button has-text-link">
<input
type="radio"
value="above"
class="sentiment-radio"
{% if params.sentiment_method == 'above' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Above">
<i class="fa-solid fa-face-smile"></i>
</span>
</label>
<label class="radio button has-text-link">
<input
type="radio"
value="nonzero"
class="sentiment-radio"
{% if params.sentiment_method == 'nonzero' %}
checked
{% endif %}
name="sentiment_method"
{% if params.check_sentiment != "on" %}
disabled
{% endif %}>
<span class="icon" data-tooltip="Nonzero">
<i class="fa-solid fa-face-meh-blank"></i>
</span>
</label>
</div>
</div>
<div class="control">
<div class="field">
<input
id="sentiment_switch"
type="checkbox"
class="switch is-rounded is-info"
name="check_sentiment"
data-script="on click toggle @disabled on #sliderWithValue then toggle @disabled on #sentiment then toggle @disabled on .sentiment-radio"
{% if params.check_sentiment == "on" %}
checked
{% endif %}>
<label
for="sentiment_switch">
Check sentiment
</label>
</div>
</div>
<div class="control">
<div class="field">
<input
id="sentiment_graph_switch"
type="checkbox"
class="switch is-rounded is-info"
name="show_sentiment"
data-script="on click toggle .is-hidden on #sentiment-container">
<label
for="sentiment_graph_switch">
Show graph
</label>
</div>
</div>
</div>
<div class="column is-narrow">
<div id="date">
<div class="field">
<div class="control">
<input type="date" name="dates" value="{{ params.date }}">
<script>
var options = {
"type": "datetime",
"isRange": true,
"color": "info",
"validateLabel": "Save",
"dateFormat": "yyyy-MM-dd",
"startDate": "{{ params.from_date|escapejs }}",
"startTime": "{{ params.from_time|escapejs }}",
"endDate": "{{ params.to_date|escapejs }}",
"endTime": "{{ params.to_time|escapejs }}",
"displayMode": "dialog"
};
// Initialize all input of type date
var calendars = bulmaCalendar.attach('[type="date"]', options);
// Loop on each calendar initialized
for(var i = 0; i < calendars.length; i++) {
// Add listener to select event
calendars[i].on('save', date => {
htmx.trigger("#search", "click");
});
}
</script>
</div>
</div>
<div class="control">
<label class="radio button has-text-link">
<input
type="radio"
value="desc"
name="sorting"
{% if params.sorting == None %}
checked
{% elif params.sorting == 'desc' %}
checked
{% endif %}>
<span class="icon" data-tooltip="Sort descending">
<i class="fa-solid fa-sort-down"></i>
</span>
</label>
<label class="radio button">
<input
type="radio"
value="asc"
name="sorting"
{% if params.sorting == 'asc' %}
checked
{% endif %}>
<span class="icon" data-tooltip="Sort ascending">
<i class="fa-solid fa-sort-up"></i>
</span>
</label>
<label class="radio button">
<input
type="radio"
value="none"
name="sorting"
{% if params.sorting == 'none' %}
checked
{% endif %}>
<span class="icon" data-tooltip="No sort">
<i class="fa-solid fa-sort"></i>
</span>
</label>
</div>
</div>
</div>
<div class="column is-narrow rounded-tooltip">
<div class="field has-addons">
<div class="control has-icons-left">
<span class="select is-warning">
<select {% if not user.is_superuser %}disabled{% endif %} id="index" name="index">
{% if params.index == 'main' %}
<option selected value="main">Main</option>
{% elif params.index == None %}
<option selected value="main">Main</option>
{% else %}
<option value="main">Main</option>
{% endif %}
{% if params.index == 'int' %}
<option selected value="int">Internal</option>
{% else %}
<option value="int">Internal</option>
{% endif %}
{% if params.index == 'meta' %}
<option selected value="meta">Meta</option>
{% else %}
<option value="meta">Meta</option>
{% endif %}
</select>
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</span>
</div>
<p class="control">
<a class="button is-static">
index
</a>
</p>
</div>
{% if not user.is_superuser %}
<span class="tooltiptext tag is-danger is-light">No access</span>
{% endif %}
</div>
</div>
</div>
<div class="block">
<input
hx-trigger="change"
hx-post="{% url 'search' %}"
hx-target="#results"
hx-swap="innerHTML"
id="tags"
class="input"
type="tags"
name="tags"
placeholder="Tag search: nick: john"
value="{{ params.tags }}">
</div>
<div class="is-hidden"></div>
</form>

View File

@@ -3,8 +3,8 @@
</div>
{% if params.index != 'int' and params.index != 'meta' %}
<div id="sentiment-container" {% if params.show_sentiment is None %} class="is-hidden" {% endif %}>
<canvas id="sentiment-chart"></canvas>
</div>
<script src="{% static 'chart.js' %}"></script>
<div id="sentiment-container" {% if params.show_sentiment is None %} class="is-hidden" {% endif %}>
<canvas id="sentiment-chart"></canvas>
</div>
<script src="{% static 'chart.js' %}"></script>
{% endif %}

View File

@@ -22,10 +22,10 @@
{% for column in table.columns %}
{% if column.name in show %}
<a class="btn-shift-column dropdown-item"
data-td-class="{{ column.name }}"
data-state="on"
{% if not forloop.last %} style="border-bottom:1px solid #ccc;" {%endif %}
data-table-class-container="drilldown-table">
data-td-class="{{ column.name }}"
data-state="on"
{% if not forloop.last %} style="border-bottom:1px solid #ccc;" {%endif %}
data-table-class-container="drilldown-table">
<span class="check icon" data-tooltip="Visible" style="display:none;">
<i class="fa-solid fa-check"></i>
</span>
@@ -125,13 +125,13 @@
</tr>
{% else %}
<tr class="
{% if row.cells.exemption == True %}has-background-grey-lighter
{% elif cell == 'join' %}has-background-success-light
{% elif cell == 'quit' %}has-background-danger-light
{% elif cell == 'kick' %}has-background-danger-light
{% elif cell == 'part' %}has-background-warning-light
{% elif cell == 'mode' %}has-background-info-light
{% endif %}">
{% if row.cells.exemption == True %}has-background-grey-lighter
{% elif cell == 'join' %}has-background-success-light
{% elif cell == 'quit' %}has-background-danger-light
{% elif cell == 'kick' %}has-background-danger-light
{% elif cell == 'part' %}has-background-warning-light
{% elif cell == 'mode' %}has-background-info-light
{% endif %}">
{% for column, cell in row.items %}
{% if column.name in show %}
{% block table.tbody.td %}
@@ -147,7 +147,7 @@
</td>
{% elif column.name == 'src' %}
<td class="{{ column.name }}">
<a
<a
class="has-text-link is-underlined"
onclick="populateSearch('src', '{{ cell|escapejs }}')">
{% if row.cells.src == 'irc' %}
@@ -172,7 +172,7 @@
</td>
{% elif column.name == 'type' or column.name == 'mtype' %}
<td class="{{ column.name }}">
<a
<a
class="has-text-link is-underlined"
onclick="populateSearch('{{ column.name }}', '{{ cell|escapejs }}')">
{% if cell == 'msg' %}
@@ -247,17 +247,17 @@
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_context' %}"
hx-vals='{"net": "{{ row.cells.net|escapejs }}",
"num": "{{ row.cells.num|escapejs }}",
"source": "{{ row.cells.src|escapejs }}",
"channel": "{{ row.cells.channel|escapejs }}",
"time": "{{ row.cells.time|escapejs }}",
"date": "{{ row.cells.date|escapejs }}",
"index": "{{ params.index }}",
"type": "{{ row.cells.type }}",
"mtype": "{{ row.cells.mtype }}",
"nick": "{{ row.cells.nick|escapejs }}",
"dedup": "{{ params.dedup }}"}'
hx-target="#modals-here"
"num": "{{ row.cells.num|escapejs }}",
"source": "{{ row.cells.src|escapejs }}",
"channel": "{{ row.cells.channel|escapejs }}",
"time": "{{ row.cells.time|escapejs }}",
"date": "{{ row.cells.date|escapejs }}",
"index": "{{ params.index }}",
"type": "{{ row.cells.type }}",
"mtype": "{{ row.cells.mtype }}",
"nick": "{{ row.cells.nick|escapejs }}",
"dedup": "{{ params.dedup }}"}'
hx-target="#modals-here"
hx-trigger="click"
href="/?modal=context&net={{row.cells.net|escapejs}}&num={{row.cells.num|escapejs}}&source={{row.cells.src|escapejs}}&channel={{row.cells.channel|urlsafe}}&time={{row.cells.time|escapejs}}&date={{row.cells.date|escapejs}}&index={{params.index}}&type={{row.cells.type}}&mtype={{row.cells.mtype}}&nick={{row.cells.mtype|escapejs}}">
{{ row.cells.msg }}
@@ -290,7 +290,7 @@
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_drilldown' %}"
hx-vals='{"net": "{{ row.cells.net }}", "nick": "{{ row.cells.nick }}", "channel": "{{ row.cells.channel }}"}'
hx-target="#modals-here"
hx-target="#modals-here"
hx-trigger="click"
class="has-text-black">
<span class="icon" data-tooltip="Open drilldown modal">
@@ -313,7 +313,7 @@
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_drilldown' type='widget' %}"
hx-vals='{"net": "{{ row.cells.net }}", "nick": "{{ row.cells.nick }}", "channel": "{{ row.cells.channel }}"}'
hx-target="#widgets-here"
hx-target="#widgets-here"
hx-trigger="click"
class="has-text-black">
<span class="icon" data-tooltip="Open drilldown widget">
@@ -335,7 +335,7 @@
<td class="{{ column.name }}">
{% if cell != '—' %}
<div class="nowrap-parent">
<a
<a
class="nowrap-child has-text-link is-underlined"
onclick="populateSearch('channel', '{{ cell|escapejs }}')">
{{ cell }}
@@ -366,7 +366,7 @@
</td>
{% else %}
<td class="{{ column.name }}">
<a
<a
class="has-text-link is-underlined"
onclick="populateSearch('{{ column.name }}', '{{ cell|escapejs }}')">
{{ cell }}
@@ -444,7 +444,7 @@
disabled
{% endif %}
style="order:3;"
>
>
{% block pagination.next.text %}
<span aria-hidden="true">&raquo;</span>
{% endblock pagination.next.text %}
@@ -469,7 +469,7 @@
hx-swap="innerHTML"
hx-indicator="#spinner"
{% endif %}
>
>
{% if p == '...' %}
<span class="pagination-ellipsis">&hellip;</span>
{% else %}

View File

@@ -1,30 +1,30 @@
{% load index %}
<div id="channels">
<div class="content" style="max-height: 30em; overflow: auto;">
<table class="table is-fullwidth is-hoverable">
<tbody>
{% for chan in chans %}
<tr>
<td>
<span
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_drilldown' %}"
hx-vals='{"net": "{{ net }}", "nick": "{{ nick }}", "channel": "{{ chan }}"}'
hx-target="#modals-here"
hx-trigger="click"
class="button is-small">
{{ chan }}
</span>
{% if chan in num_users %}
<span class="tag">
{{ num_users|index:chan }}
</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="content" style="max-height: 30em; overflow: auto;">
<table class="table is-fullwidth is-hoverable">
<tbody>
{% for chan in chans %}
<tr>
<td>
<span
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_drilldown' %}"
hx-vals='{"net": "{{ net }}", "nick": "{{ nick }}", "channel": "{{ chan }}"}'
hx-target="#modals-here"
hx-trigger="click"
class="button is-small">
{{ chan }}
</span>
{% if chan in num_users %}
<span class="tag">
{{ num_users|index:chan }}
</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>

View File

@@ -1,103 +1,103 @@
{% load static %}
{% load index %}
<div
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-vals='{"net": "{{ item.net }}", "nick": "{{ item.nick }}"}'
hx-post="{% url 'chans_insights' %}"
hx-trigger="load"
hx-target="#channels"
hx-swap="outerHTML">
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-vals='{"net": "{{ item.net }}", "nick": "{{ item.nick }}"}'
hx-post="{% url 'chans_insights' %}"
hx-trigger="load"
hx-target="#channels"
hx-swap="outerHTML">
</div>
<div
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-vals='{"net": "{{ item.net }}", "nick": "{{ item.nick }}"}'
hx-post="{% url 'nicks_insights' %}"
hx-trigger="load"
hx-target="#nicks"
hx-swap="outerHTML">
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-vals='{"net": "{{ item.net }}", "nick": "{{ item.nick }}"}'
hx-post="{% url 'nicks_insights' %}"
hx-trigger="load"
hx-target="#nicks"
hx-swap="outerHTML">
</div>
<div id="info">
{% include 'partials/notify.html' %}
{% if item is not None %}
<div class="content" style="max-height: 30em; overflow: auto;">
<div class="table-container">
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
<tr>
<th>src</th>
<td>
{% if item.src == 'irc' %}
<span class="icon" data-tooltip="IRC">
<i class="fa-solid fa-hashtag" aria-hidden="true"></i>
</span>
IRC
{% elif item.src == 'dis' %}
<span class="icon" data-tooltip="Discord">
<i class="fa-brands fa-discord" aria-hidden="true"></i>
</span>
Discord
{% endif %}
</td>
</tr>
<tr>
<th>nick</th>
<td>
{% if item.online is True %}
<span class="icon has-text-success has-tooltip-success" data-tooltip="Online">
<i class="fa-solid fa-circle"></i>
</span>
{{ item.nick }}
{% elif item.online is False %}
<span class="icon has-text-danger has-tooltip-danger" data-tooltip="Offline">
<i class="fa-solid fa-circle"></i>
</span>
{{ item.nick }}
{% else %}
<span class="icon has-text-warning has-tooltip-warning" data-tooltip="Unknown">
<i class="fa-solid fa-circle"></i>
</span>
{{ item.nick }}
{% endif %}
{% if item.num_chans is not None %}
<span class="tag">
{{ item.num_chans }}
</span>
{% endif %}
</td>
</tr>
<tr>
<th>host</th>
<td>{{ item.host }}</td>
</tr>
<tr>
<th>actions</th>
<td>
{% if item.src == 'irc' %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_insights' %}"
hx-vals='{"net": "{{ item.net }}", "nick": "{{ item.nick }}", "channel": "{{ item.channel }}"}'
hx-target="#modals-here"
hx-trigger="click"
class="button is-small">
Information
</button>
{% endif %}
</td>
</tr>
<tr>
<th>net</th>
<td>{{ item.net }}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endif %}
{% include 'partials/notify.html' %}
{% if item is not None %}
<div class="content" style="max-height: 30em; overflow: auto;">
<div class="table-container">
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
<tr>
<th>src</th>
<td>
{% if item.src == 'irc' %}
<span class="icon" data-tooltip="IRC">
<i class="fa-solid fa-hashtag" aria-hidden="true"></i>
</span>
IRC
{% elif item.src == 'dis' %}
<span class="icon" data-tooltip="Discord">
<i class="fa-brands fa-discord" aria-hidden="true"></i>
</span>
Discord
{% endif %}
</td>
</tr>
<tr>
<th>nick</th>
<td>
{% if item.online is True %}
<span class="icon has-text-success has-tooltip-success" data-tooltip="Online">
<i class="fa-solid fa-circle"></i>
</span>
{{ item.nick }}
{% elif item.online is False %}
<span class="icon has-text-danger has-tooltip-danger" data-tooltip="Offline">
<i class="fa-solid fa-circle"></i>
</span>
{{ item.nick }}
{% else %}
<span class="icon has-text-warning has-tooltip-warning" data-tooltip="Unknown">
<i class="fa-solid fa-circle"></i>
</span>
{{ item.nick }}
{% endif %}
{% if item.num_chans is not None %}
<span class="tag">
{{ item.num_chans }}
</span>
{% endif %}
</td>
</tr>
<tr>
<th>host</th>
<td>{{ item.host }}</td>
</tr>
<tr>
<th>actions</th>
<td>
{% if item.src == 'irc' %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_insights' %}"
hx-vals='{"net": "{{ item.net }}", "nick": "{{ item.nick }}", "channel": "{{ item.channel }}"}'
hx-target="#modals-here"
hx-trigger="click"
class="button is-small">
Information
</button>
{% endif %}
</td>
</tr>
<tr>
<th>net</th>
<td>{{ item.net }}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endif %}
</div>

View File

@@ -1,101 +1,101 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
{% include 'partials/notify.html' %}
<script>
// tabbed browsing for the modal
function initTabs() {
TABS.forEach((tab) => {
tab.addEventListener('click', (e) => {
let selected = tab.getAttribute('data-tab');
updateActiveTab(tab);
updateActiveContent(selected);
})
})
{% include 'partials/notify.html' %}
<script>
// tabbed browsing for the modal
function initTabs() {
TABS.forEach((tab) => {
tab.addEventListener('click', (e) => {
let selected = tab.getAttribute('data-tab');
updateActiveTab(tab);
updateActiveContent(selected);
})
})
}
function updateActiveTab(selected) {
TABS.forEach((tab) => {
if (tab && tab.classList.contains(ACTIVE_CLASS)) {
tab.classList.remove(ACTIVE_CLASS);
}
});
selected.classList.add(ACTIVE_CLASS);
}
function updateActiveTab(selected) {
TABS.forEach((tab) => {
if (tab && tab.classList.contains(ACTIVE_CLASS)) {
tab.classList.remove(ACTIVE_CLASS);
}
});
selected.classList.add(ACTIVE_CLASS);
function updateActiveContent(selected) {
CONTENT.forEach((item) => {
if (item && item.classList.contains(ACTIVE_CLASS)) {
item.classList.remove(ACTIVE_CLASS);
}
function updateActiveContent(selected) {
CONTENT.forEach((item) => {
if (item && item.classList.contains(ACTIVE_CLASS)) {
item.classList.remove(ACTIVE_CLASS);
}
let data = item.getAttribute('data-content');
if (data === selected) {
item.classList.add(ACTIVE_CLASS);
}
});
let data = item.getAttribute('data-content');
if (data === selected) {
item.classList.add(ACTIVE_CLASS);
}
</script>
<style>
.icon { border-bottom: 0px !important;}
</style>
<div class="tile is-ancestor">
<div class="tile is-vertical is-9">
<div class="tile">
<div class="tile is-parent is-vertical">
<article class="tile is-child box">
<form method="POST">
{% csrf_token %}
<div class="field has-addons">
<div class="control is-expanded has-icons-left">
<input id="query_full" name="query_full" class="input" type="text" placeholder="nickname">
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</div>
<div class="control">
<button
class="button is-info is-fullwidth"
hx-post="{% url 'search_insights' %}"
hx-trigger="click"
hx-target="#info"
hx-swap="outerHTML">
Search
</button>
</div>
</div>
</form>
</article>
});
}
</script>
<style>
.icon { border-bottom: 0px !important;}
</style>
<div class="tile is-ancestor">
<div class="tile is-vertical is-9">
<div class="tile">
<div class="tile is-parent is-vertical">
<article class="tile is-child box">
<form method="POST">
{% csrf_token %}
<div class="field has-addons">
<div class="control is-expanded has-icons-left">
<input id="query_full" name="query_full" class="input" type="text" placeholder="nickname">
<span class="icon is-small is-left">
<i class="fas fa-magnifying-glass"></i>
</span>
</div>
<div class="control">
<button
class="button is-info is-fullwidth"
hx-post="{% url 'search_insights' %}"
hx-trigger="click"
hx-target="#info"
hx-swap="outerHTML">
Search
</button>
</div>
</div>
</form>
</article>
</div>
<div class="tile is-parent">
<article class="tile is-child box">
<h5 class="subtitle is-5">Nicks</h5>
<div id="nicks"></div>
</article>
</div>
</div>
<div class="tile">
<div class="tile is-parent is-vertical">
<article class="tile is-child box">
<h5 class="subtitle is-5">Info</h5>
<div id="info"></div>
</article>
</div>
<div class="tile is-parent">
<article class="tile is-child box">
<h5 class="subtitle is-5">Meta</h5>
<div id="meta"></div>
</article>
</div>
</div>
</div>
<div class="tile is-parent">
<article class="tile is-child box">
<h5 class="subtitle is-5">Channels</h5>
<div id="channels"></div>
</article>
<article class="tile is-child box">
<h5 class="subtitle is-5">Nicks</h5>
<div id="nicks"></div>
</article>
</div>
</div>
<div class="tile">
<div class="tile is-parent is-vertical">
<article class="tile is-child box">
<h5 class="subtitle is-5">Info</h5>
<div id="info"></div>
</article>
</div>
<div class="tile is-parent">
<article class="tile is-child box">
<h5 class="subtitle is-5">Meta</h5>
<div id="meta"></div>
</article>
</div>
</div>
</div>
<div id="modals-here"></div>
<div class="tile is-parent">
<article class="tile is-child box">
<h5 class="subtitle is-5">Channels</h5>
<div id="channels"></div>
</article>
</div>
</div>
<div id="modals-here"></div>
{% endblock %}

View File

@@ -1,20 +1,20 @@
<div id="meta">
<div class="content" style="max-height: 30em; overflow: auto;">
<div class="table-container">
{% for key,items in meta.items %}
<th><strong>{{ key }}</strong></th>
<table class="table is-fullwidth is-hoverable">
<tbody>
{% for item in items %}
<tr>
<td>
{{ item }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="content" style="max-height: 30em; overflow: auto;">
<div class="table-container">
{% for key,items in meta.items %}
<th><strong>{{ key }}</strong></th>
<table class="table is-fullwidth is-hoverable">
<tbody>
{% for item in items %}
<tr>
<td>
{{ item }}
</td>
</tr>
{% endfor %}
</div>
</tbody>
</table>
{% endfor %}
</div>
</div>
</div>

View File

@@ -1,54 +1,54 @@
{% load index %}
<div
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-vals='{"net": "{{ net }}", "nicks": "{{ nicks }}"}'
hx-post="{% url 'meta_insights' %}"
hx-trigger="load"
hx-target="#meta"
hx-swap="outerHTML">
style="display: none;"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-vals='{"net": "{{ net }}", "nicks": "{{ nicks }}"}'
hx-post="{% url 'meta_insights' %}"
hx-trigger="load"
hx-target="#meta"
hx-swap="outerHTML">
</div>
<div id="nicks">
<div class="content" style="max-height: 30em; overflow: auto;">
<table class="table is-fullwidth is-hoverable">
<tbody>
{% for nick in nicks %}
<tr>
<td>
{% if nick in online %}
{% if online|index:nick is True %}
<span class="icon has-text-success has-tooltip-success" data-tooltip="Online">
<i class="fa-solid fa-circle"></i>
</span>
{% elif online|index:nick is False %}
<span class="icon has-text-danger has-tooltip-danger" data-tooltip="Offline">
<i class="fa-solid fa-circle"></i>
</span>
{% else %}
<span class="icon has-text-warning has-tooltip-warning" data-tooltip="Unknown">
<i class="fa-solid fa-circle"></i>
</span>
{% endif %}
{% endif %}
<span
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_drilldown' %}"
hx-vals='{"net": "{{ net }}", "nick": "{{ nick }}", "channel": "{{ chan }}"}'
hx-target="#modals-here"
hx-trigger="click"
class="button is-small">
{{ nick }}
</span>
<a
class="icon has-text-info has-tooltip-info"
data-tooltip="Populate search"
onclick="document.getElementById('query').value='nick: {{ nick }}';">
<i class="fa-solid fa-arrow-left-long-to-line"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="content" style="max-height: 30em; overflow: auto;">
<table class="table is-fullwidth is-hoverable">
<tbody>
{% for nick in nicks %}
<tr>
<td>
{% if nick in online %}
{% if online|index:nick is True %}
<span class="icon has-text-success has-tooltip-success" data-tooltip="Online">
<i class="fa-solid fa-circle"></i>
</span>
{% elif online|index:nick is False %}
<span class="icon has-text-danger has-tooltip-danger" data-tooltip="Offline">
<i class="fa-solid fa-circle"></i>
</span>
{% else %}
<span class="icon has-text-warning has-tooltip-warning" data-tooltip="Unknown">
<i class="fa-solid fa-circle"></i>
</span>
{% endif %}
{% endif %}
<span
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'modal_drilldown' %}"
hx-vals='{"net": "{{ net }}", "nick": "{{ nick }}", "channel": "{{ chan }}"}'
hx-target="#modals-here"
hx-trigger="click"
class="button is-small">
{{ nick }}
</span>
<a
class="icon has-text-info has-tooltip-info"
data-tooltip="Populate search"
onclick="document.getElementById('query').value='nick: {{ nick }}';">
<i class="fa-solid fa-arrow-left-long-to-line"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>