mirror of
https://github.com/dalbodeule/snap-admin.git
synced 2025-08-13 15:11:14 +00:00
WIP
This commit is contained in:
@@ -181,6 +181,19 @@ AUTOCOMPLETE
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
|
||||
ul.categorical-select {
|
||||
list-style-type: none;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ul.categorical-select button {
|
||||
color: #007fd0;
|
||||
text-decoration: underline;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Images
|
||||
*/
|
||||
|
@@ -9,7 +9,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
activeFilters.forEach(activeFilter => {
|
||||
activeFilter.addEventListener('click', function(e) {
|
||||
let formId = e.target.dataset.formid;
|
||||
document.getElementById(formId).submit()
|
||||
document.getElementById(formId).submit();
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -46,64 +46,99 @@
|
||||
<span class="fw-bold align-middle" th:text="${field.getName()}"></span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<form action="" method="GET">
|
||||
<!-- Reset page when applying filter to start back at page 1 -->
|
||||
<input type="hidden" name="page" value="1">
|
||||
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}">
|
||||
<input type="hidden" name="query" th:value="${query}">
|
||||
<input type="hidden" name="filter_field" th:value="${field.getJavaName()}">
|
||||
|
||||
<div class="input-group pe-2">
|
||||
<th:block th:if="${field.isForeignKey()}">
|
||||
<span class="input-group-text w-25">
|
||||
<input type="hidden" name="filter_op" value="string_eq">
|
||||
Equals
|
||||
</span>
|
||||
<div class="autocomplete-input position-relative w-50">
|
||||
<input class="autocomplete form-control" type="text" name="filter_value"
|
||||
th:data-classname="${field.getConnectedType().getName()}"
|
||||
autocomplete="off"
|
||||
placeholder="NULL">
|
||||
</input>
|
||||
<div class="suggestions d-none">
|
||||
<!--/*--> Propagate queryParams containing other filters with hidden fields <!--*/-->
|
||||
<th:block th:each="p : ${queryParams.keySet()}">
|
||||
<input th:each="v : ${queryParams.get(p)}"
|
||||
th:name="${p}" th:value="${v}" type="hidden"
|
||||
th:if="${p.startsWith('filter_')}">
|
||||
</th:block>
|
||||
<!--/*--> Handle non categorical filter <!--*/-->
|
||||
<th:block th:if="${!field.isFilterableCategorical()}">
|
||||
<form action="" method="GET">
|
||||
<div class="input-group pe-2">
|
||||
<!-- Reset page when applying filter to start back at page 1 -->
|
||||
<input type="hidden" name="page" value="1">
|
||||
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}">
|
||||
<input type="hidden" name="query" th:value="${query}">
|
||||
<input type="hidden" name="filter_field" th:value="${field.getJavaName()}">
|
||||
|
||||
<th:block th:if="${field.isForeignKey()}">
|
||||
<span class="input-group-text w-25">
|
||||
<input type="hidden" name="filter_op" value="string_eq">
|
||||
Equals
|
||||
</span>
|
||||
<div class="autocomplete-input position-relative w-50">
|
||||
<input class="autocomplete form-control" type="text" name="filter_value"
|
||||
th:data-classname="${field.getConnectedType().getName()}"
|
||||
autocomplete="off"
|
||||
placeholder="NULL">
|
||||
</input>
|
||||
<div class="suggestions d-none">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</th:block>
|
||||
<th:block th:unless="${field.isForeignKey()}">
|
||||
<select class="form-select w-25" name="filter_op">
|
||||
<option th:value="${op}" th:each="op : ${field.getType().getCompareOperators()}"
|
||||
th:text="${op.getDisplayName()}">
|
||||
</select>
|
||||
<input placeholder="NULL" th:type="${field.getType().getHTMLName()}"
|
||||
name="filter_value"
|
||||
class="form-control w-50" th:id="|__id_${field.getName()}|"
|
||||
th:classAppend="${field.isPrimaryKey() && object != null ? 'disable' : ''}"
|
||||
th:required="${!field.isNullable() && !field.isPrimaryKey()}"
|
||||
step="any"
|
||||
oninvalid="this.setCustomValidity('This field is not nullable.')"
|
||||
oninput="this.setCustomValidity('')">
|
||||
</th:block>
|
||||
|
||||
<th:block th:each="p : ${queryParams.keySet()}">
|
||||
<input th:each="v : ${queryParams.get(p)}"
|
||||
th:name="${p}" th:value="${v}" type="hidden"
|
||||
th:if="${p.startsWith('filter_')}">
|
||||
</th:block>
|
||||
|
||||
</th:block>
|
||||
<th:block th:unless="${field.isForeignKey()}">
|
||||
<select class="form-select w-25" name="filter_op">
|
||||
<option th:value="${op}" th:each="op : ${field.getType().getCompareOperators()}"
|
||||
th:text="${op.getDisplayName()}">
|
||||
</select>
|
||||
<input placeholder="NULL" th:type="${field.getType().getHTMLName()}"
|
||||
name="filter_value"
|
||||
class="form-control w-50" th:id="|__id_${field.getName()}|"
|
||||
th:classAppend="${field.isPrimaryKey() && object != null ? 'disable' : ''}"
|
||||
th:required="${!field.isNullable() && !field.isPrimaryKey()}"
|
||||
step="any"
|
||||
oninvalid="this.setCustomValidity('This field is not nullable.')"
|
||||
oninput="this.setCustomValidity('')">
|
||||
</th:block>
|
||||
<button class="ui-btn btn btn-primary"><i class="bi bi-search text-white"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
</th:block>
|
||||
<!--/*--> Handle categorical filter <!--*/-->
|
||||
<th:block th:if="${field.isFilterableCategorical()}">
|
||||
<th:block th:if="${field.isForeignKey()}">
|
||||
<ul class="categorical-select">
|
||||
<li th:each="categoricalValue : ${field.getConnectedSchema().findAll()}">
|
||||
<form action="" method="GET">
|
||||
<!-- Reset page when applying filter to start back at page 1 -->
|
||||
<input type="hidden" name="page" value="1">
|
||||
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}">
|
||||
<input type="hidden" name="query" th:value="${query}">
|
||||
<input type="hidden" name="filter_field" th:value="${field.getJavaName()}">
|
||||
|
||||
|
||||
<button class="ui-btn btn btn-primary"><i class="bi bi-search text-white"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!--
|
||||
<th:block th:if="${field.getConnectedType() != null}">
|
||||
<div th:each="val : ${schema.getFieldValues(field)}">
|
||||
<span th:text="${val}"></span>
|
||||
</div>
|
||||
</th:block>
|
||||
-->
|
||||
<input type="hidden" name="filter_op" value="string_eq">
|
||||
<input type="hidden" name="filter_value"
|
||||
th:value="${categoricalValue.getPrimaryKeyValue()}">
|
||||
<button class="mb-2">
|
||||
[[ ${categoricalValue.getDisplayName()} ]]
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</th:block>
|
||||
<th:block th:unless="${field.isForeignKey()}">
|
||||
<ul class="categorical-select">
|
||||
<li th:each="categoricalValue : ${field.getAllValues()}">
|
||||
<form action="" method="GET">
|
||||
<!-- Reset page when applying filter to start back at page 1 -->
|
||||
<input type="hidden" name="page" value="1">
|
||||
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}">
|
||||
<input type="hidden" name="query" th:value="${query}">
|
||||
<input type="hidden" name="filter_field" th:value="${field.getJavaName()}">
|
||||
|
||||
<input type="hidden" name="filter_op" value="string_eq">
|
||||
<input type="hidden" name="filter_value"
|
||||
th:value="${categoricalValue.getValue()}">
|
||||
<button class="mb-2">
|
||||
[[ ${categoricalValue.getFormattedValue()} ]]
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@@ -58,108 +58,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <h1 class="fw-bold mb-4"><i class="bi bi-bounding-box-circles"></i> Dashboard</h1>
|
||||
<div class="alert mt-4 alert-warning" role="alert">
|
||||
<i class="bi bi-info-circle"></i>
|
||||
<span>
|
||||
In some sections, this website displays unfiltered war footage from Telegram channels.
|
||||
This might be NSFW and/or hurt your sensibility. Proceed at your own discretion.
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col pb-4">
|
||||
<form action="/search" method="get" class="form">
|
||||
<div class="input-group">
|
||||
<input type="text" name="query" class="form-control ui-text-input" placeholder="Quick search">
|
||||
<button class="ui-btn btn btn-primary">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="box with-footer-button">
|
||||
<h3 class="fw-bold"><i class="bi bi-chat-dots"></i> Total messages</h3>
|
||||
<p class="fine">The total number of messages indexed since Feb 23, 2022.</p>
|
||||
<p class="fs-bigger" th:text="${countMessages}"></p>
|
||||
<div class="separator mb-3 mt-3"></div>
|
||||
<div class="row mt-1">
|
||||
<div class="col-6 text-center">
|
||||
<h4> <span th:text="${countMessagesOneDay}"></span></h4>
|
||||
<p class="mb-0 text-center fw-bold">LAST 24 HOURS</p>
|
||||
</div>
|
||||
<div class="col-6 text-center">
|
||||
<h4> <span th:text="${countMessagesOneHour}"></span></h4>
|
||||
<p class="mb-0 text-center fw-bold">LAST HOUR</p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/search"
|
||||
class="text-decoration-none color-black">
|
||||
<div class="explore-channel text-center">
|
||||
<p class="m-0 p-0">
|
||||
SEARCH MESSAGES
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 mt-4 mt-lg-0">
|
||||
<div class="box with-footer-button">
|
||||
<h3 class="fw-bold"><i class="bi bi-megaphone"></i> Total channels</h3>
|
||||
<p class="fine">The total number of channels, a fraction of which is actively indexed.</p>
|
||||
<p class="fs-bigger" th:text="${countChannels}"></p>
|
||||
<div class="separator mb-3 mt-3"></div>
|
||||
<div class="row mt-1">
|
||||
<div class="col-4 text-center">
|
||||
<h4> <span class="fw-bold" th:text="${countChannelsEn}"></span></h4>
|
||||
<p class="mb-0 text-center fw-bold">🇬🇧 English</p>
|
||||
</div>
|
||||
<div class="col-4 text-center">
|
||||
<h4> <span class="fw-bold" th:text="${countChannelsRu}"></span></h4>
|
||||
<p class="mb-0 text-center fw-bold">🇷🇺 Russian</p>
|
||||
</div>
|
||||
<div class="col-4 text-center">
|
||||
<h4> <span class="fw-bold" th:text="${countChannelsUa}"></span></h4>
|
||||
<p class="mb-0 text-center fw-bold">🇺🇦 Ukrainian</p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/channels"
|
||||
class="text-decoration-none color-black">
|
||||
<div class="explore-channel text-center">
|
||||
<p class="m-0 p-0">
|
||||
EXPLORE CHANNELS
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-lg-12 col-xxl-8">
|
||||
<div class="box d-none d-sm-block">
|
||||
<h3 class="fw-bold"><i class="bi bi-graph-up"></i> Messages per day</h3>
|
||||
A
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12 col-xxl-4 mt-4 mt-xxl-0 ">
|
||||
<div class="box">
|
||||
<h3 class="fw-bold mb-4"><i class="bi bi-graph-up-arrow"></i> Trending topics</h3>
|
||||
CIAO
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -81,7 +81,8 @@
|
||||
<span title="Click to remove this filter"
|
||||
class="active-filter badge bg-primary me-1 mb-2 p-2 font-monospace cursor-pointer noselect"
|
||||
th:data-formid="${filter.toString()}"
|
||||
th:text="${filter}">
|
||||
>
|
||||
[[ ${filter}]] <!-- <i class="bi bi-x-circle"></i> -->
|
||||
</span>
|
||||
<form action="" th:id="${filter.toString()}" method="GET">
|
||||
<th:block th:each="p : ${queryParams.keySet()}">
|
||||
|
Reference in New Issue
Block a user