mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-01-11 20:00:26 +01:00
feat(transactions:filter): make montlhy summary filter-aware
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
# apps/dca_tracker/views.py
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.db.models import Sum, Avg
|
from django.db.models import Sum, Avg
|
||||||
@@ -234,7 +233,7 @@ def strategy_entry_add(request, strategy_id):
|
|||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = DCAEntryForm(request.POST, strategy=strategy)
|
form = DCAEntryForm(request.POST, strategy=strategy)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
entry = form.save()
|
form.save()
|
||||||
messages.success(request, _("Entry added successfully"))
|
messages.success(request, _("Entry added successfully"))
|
||||||
|
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ from django.contrib.auth.decorators import login_required
|
|||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Q,
|
Q,
|
||||||
)
|
)
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse, Http404
|
||||||
|
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
@@ -36,8 +37,6 @@ def monthly_overview(request, month: int, year: int):
|
|||||||
summary_tab = request.session.get("monthly_summary_tab", "summary")
|
summary_tab = request.session.get("monthly_summary_tab", "summary")
|
||||||
|
|
||||||
if month < 1 or month > 12:
|
if month < 1 or month > 12:
|
||||||
from django.http import Http404
|
|
||||||
|
|
||||||
raise Http404("Month is out of range")
|
raise Http404("Month is out of range")
|
||||||
|
|
||||||
next_month = 1 if month == 12 else month + 1
|
next_month = 1 if month == 12 else month + 1
|
||||||
@@ -107,17 +106,48 @@ def transactions_list(request, month: int, year: int):
|
|||||||
@require_http_methods(["GET"])
|
@require_http_methods(["GET"])
|
||||||
def monthly_summary(request, month: int, year: int):
|
def monthly_summary(request, month: int, year: int):
|
||||||
# Base queryset with all required filters
|
# Base queryset with all required filters
|
||||||
base_queryset = (
|
base_queryset = Transaction.objects.filter(
|
||||||
Transaction.objects.filter(
|
reference_date__year=year,
|
||||||
reference_date__year=year,
|
reference_date__month=month,
|
||||||
reference_date__month=month,
|
|
||||||
account__is_asset=False,
|
|
||||||
)
|
|
||||||
.exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
|
||||||
.exclude(account__in=request.user.untracked_accounts.all())
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data = calculate_currency_totals(base_queryset, ignore_empty=True)
|
# Apply filters and check if any are active
|
||||||
|
f = TransactionsFilter(request.GET, queryset=base_queryset)
|
||||||
|
|
||||||
|
# Check if any filter has a non-default value
|
||||||
|
# Default values are: type=['IN', 'EX'], is_paid=['1', '0'], everything else empty
|
||||||
|
has_active_filter = False
|
||||||
|
if f.form.is_valid():
|
||||||
|
for name, value in f.form.cleaned_data.items():
|
||||||
|
# Skip fields with default/empty values
|
||||||
|
if not value:
|
||||||
|
continue
|
||||||
|
# Skip type if it has both default values
|
||||||
|
if name == "type" and set(value) == {"IN", "EX"}:
|
||||||
|
continue
|
||||||
|
# Skip is_paid if it has both default values (values are strings)
|
||||||
|
if name == "is_paid" and set(value) == {"1", "0"}:
|
||||||
|
continue
|
||||||
|
# Skip mute_status if it has both default values
|
||||||
|
if name == "mute_status" and set(value) == {"active", "muted"}:
|
||||||
|
continue
|
||||||
|
# If we get here, there's an active filter
|
||||||
|
has_active_filter = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if has_active_filter:
|
||||||
|
queryset = f.qs
|
||||||
|
else:
|
||||||
|
queryset = (
|
||||||
|
base_queryset.exclude(
|
||||||
|
Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True)
|
||||||
|
)
|
||||||
|
.exclude(account__in=request.user.untracked_accounts.all())
|
||||||
|
.exclude(account__is_asset=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
data = calculate_currency_totals(queryset, ignore_empty=True)
|
||||||
|
|
||||||
percentages = calculate_percentage_distribution(data)
|
percentages = calculate_percentage_distribution(data)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
@@ -132,6 +162,7 @@ def monthly_summary(request, month: int, year: int):
|
|||||||
currency_totals=data, month=month, year=year
|
currency_totals=data, month=month, year=year
|
||||||
),
|
),
|
||||||
"percentages": percentages,
|
"percentages": percentages,
|
||||||
|
"has_active_filter": has_active_filter,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
@@ -149,9 +180,38 @@ def monthly_account_summary(request, month: int, year: int):
|
|||||||
base_queryset = Transaction.objects.filter(
|
base_queryset = Transaction.objects.filter(
|
||||||
reference_date__year=year,
|
reference_date__year=year,
|
||||||
reference_date__month=month,
|
reference_date__month=month,
|
||||||
).exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
)
|
||||||
|
|
||||||
account_data = calculate_account_totals(transactions_queryset=base_queryset.all())
|
# Apply filters and check if any are active
|
||||||
|
f = TransactionsFilter(request.GET, queryset=base_queryset)
|
||||||
|
|
||||||
|
# Check if any filter has a non-default value
|
||||||
|
has_active_filter = False
|
||||||
|
if f.form.is_valid():
|
||||||
|
for name, value in f.form.cleaned_data.items():
|
||||||
|
if not value:
|
||||||
|
continue
|
||||||
|
if name == "type" and set(value) == {"IN", "EX"}:
|
||||||
|
continue
|
||||||
|
if name == "is_paid" and set(value) == {"1", "0"}:
|
||||||
|
continue
|
||||||
|
if name == "mute_status" and set(value) == {"active", "muted"}:
|
||||||
|
continue
|
||||||
|
has_active_filter = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if has_active_filter:
|
||||||
|
queryset = f.qs
|
||||||
|
else:
|
||||||
|
queryset = (
|
||||||
|
base_queryset.exclude(
|
||||||
|
Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True)
|
||||||
|
)
|
||||||
|
.exclude(account__in=request.user.untracked_accounts.all())
|
||||||
|
.exclude(account__is_asset=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
account_data = calculate_account_totals(transactions_queryset=queryset.all())
|
||||||
account_percentages = calculate_percentage_distribution(account_data)
|
account_percentages = calculate_percentage_distribution(account_data)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
@@ -171,16 +231,41 @@ def monthly_account_summary(request, month: int, year: int):
|
|||||||
@require_http_methods(["GET"])
|
@require_http_methods(["GET"])
|
||||||
def monthly_currency_summary(request, month: int, year: int):
|
def monthly_currency_summary(request, month: int, year: int):
|
||||||
# Base queryset with all required filters
|
# Base queryset with all required filters
|
||||||
base_queryset = (
|
base_queryset = Transaction.objects.filter(
|
||||||
Transaction.objects.filter(
|
reference_date__year=year,
|
||||||
reference_date__year=year,
|
reference_date__month=month,
|
||||||
reference_date__month=month,
|
|
||||||
)
|
|
||||||
.exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
|
||||||
.exclude(account__in=request.user.untracked_accounts.all())
|
|
||||||
)
|
)
|
||||||
|
|
||||||
currency_data = calculate_currency_totals(base_queryset.all(), ignore_empty=True)
|
# Apply filters and check if any are active
|
||||||
|
f = TransactionsFilter(request.GET, queryset=base_queryset)
|
||||||
|
|
||||||
|
# Check if any filter has a non-default value
|
||||||
|
has_active_filter = False
|
||||||
|
if f.form.is_valid():
|
||||||
|
for name, value in f.form.cleaned_data.items():
|
||||||
|
if not value:
|
||||||
|
continue
|
||||||
|
if name == "type" and set(value) == {"IN", "EX"}:
|
||||||
|
continue
|
||||||
|
if name == "is_paid" and set(value) == {"1", "0"}:
|
||||||
|
continue
|
||||||
|
if name == "mute_status" and set(value) == {"active", "muted"}:
|
||||||
|
continue
|
||||||
|
has_active_filter = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if has_active_filter:
|
||||||
|
queryset = f.qs
|
||||||
|
else:
|
||||||
|
queryset = (
|
||||||
|
base_queryset.exclude(
|
||||||
|
Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True)
|
||||||
|
)
|
||||||
|
.exclude(account__in=request.user.untracked_accounts.all())
|
||||||
|
.exclude(account__is_asset=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
currency_data = calculate_currency_totals(queryset.all(), ignore_empty=True)
|
||||||
currency_percentages = calculate_percentage_distribution(currency_data)
|
currency_percentages = calculate_percentage_distribution(currency_data)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load currency_display %}
|
{% load currency_display %}
|
||||||
<div class="grid grid-cols-1 gap-4 mt-1 mb-3">
|
<div class="grid grid-cols-1 gap-4 mt-1 mb-3">
|
||||||
|
{% if not has_active_filter %}
|
||||||
{# Daily Spending#}
|
{# Daily Spending#}
|
||||||
<div>
|
<div>
|
||||||
<c-ui.info-card color="yellow" icon="fa-solid fa-calendar-day" title="{% trans 'Daily Spending Allowance' %}" help_text={% trans "This is the final total divided by the remaining days in the month" %}>
|
<c-ui.info-card color="yellow" icon="fa-solid fa-calendar-day" title="{% trans 'Daily Spending Allowance' %}" help_text={% trans "This is the final total divided by the remaining days in the month" %}>
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</c-ui.info-card>
|
</c-ui.info-card>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
{# Income#}
|
{# Income#}
|
||||||
<div>
|
<div>
|
||||||
<c-ui.info-card color="green" icon="fa-solid fa-arrow-right-to-bracket" title="{% trans 'Income' %}">
|
<c-ui.info-card color="green" icon="fa-solid fa-arrow-right-to-bracket" title="{% trans 'Income' %}">
|
||||||
|
|||||||
@@ -50,12 +50,13 @@
|
|||||||
role="tab"
|
role="tab"
|
||||||
{% if summary_tab == 'summary' or not summary_tab %}checked="checked"{% endif %}
|
{% if summary_tab == 'summary' or not summary_tab %}checked="checked"{% endif %}
|
||||||
_="on click fetch {% url 'monthly_summary_select' selected='summary' %}"
|
_="on click fetch {% url 'monthly_summary_select' selected='summary' %}"
|
||||||
aria-controls="summary-tab-pane" />
|
aria-controls="summary-tab-pane"/>
|
||||||
<div class="tab-content" id="summary-tab-pane" role="tabpanel">
|
<div class="tab-content" id="summary-tab-pane" role="tabpanel">
|
||||||
<div id="summary"
|
<div id="summary"
|
||||||
hx-get="{% url 'monthly_summary' month=month year=year %}"
|
hx-get="{% url 'monthly_summary' month=month year=year %}"
|
||||||
class="show-loading"
|
class="show-loading"
|
||||||
hx-trigger="load, updated from:window, selective_update from:window, every 10m">
|
hx-trigger="load, updated from:window, selective_update from:window, every 10m"
|
||||||
|
hx-include="#filter">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -68,7 +69,8 @@
|
|||||||
<div id="currency-summary"
|
<div id="currency-summary"
|
||||||
hx-get="{% url 'monthly_currency_summary' month=month year=year %}"
|
hx-get="{% url 'monthly_currency_summary' month=month year=year %}"
|
||||||
class="show-loading"
|
class="show-loading"
|
||||||
hx-trigger="load, updated from:window, selective_update from:window, every 10m">
|
hx-trigger="load, updated from:window, selective_update from:window, every 10m"
|
||||||
|
hx-include="#filter">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -81,7 +83,8 @@
|
|||||||
<div id="account-summary"
|
<div id="account-summary"
|
||||||
hx-get="{% url 'monthly_account_summary' month=month year=year %}"
|
hx-get="{% url 'monthly_account_summary' month=month year=year %}"
|
||||||
class="show-loading"
|
class="show-loading"
|
||||||
hx-trigger="load, updated from:window, selective_update from:window, every 10m">
|
hx-trigger="load, updated from:window, selective_update from:window, every 10m"
|
||||||
|
hx-include="#filter">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,11 +103,112 @@
|
|||||||
{# Main control bar with filter, search, and ordering #}
|
{# Main control bar with filter, search, and ordering #}
|
||||||
<div class="join w-full">
|
<div class="join w-full">
|
||||||
|
|
||||||
<button class="btn btn-secondary join-item relative" type="button"
|
<button class="btn btn-secondary join-item relative z-1" type="button"
|
||||||
@click="filterOpen = !filterOpen"
|
@click="filterOpen = !filterOpen"
|
||||||
:aria-expanded="filterOpen" id="filter-button"
|
:aria-expanded="filterOpen" id="filter-button"
|
||||||
title="{% translate 'Filter transactions' %}">
|
title="{% translate 'Filter transactions' %}"
|
||||||
|
_="on load or change from #filter
|
||||||
|
-- Check if any filter has a non-default value
|
||||||
|
set hasActiveFilter to false
|
||||||
|
|
||||||
|
-- Check type (default is both IN and EX checked)
|
||||||
|
set typeInputs to <input[name='type']:checked/> in #filter
|
||||||
|
if typeInputs.length is not 2
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check is_paid (default is both 1 and 0 checked)
|
||||||
|
set isPaidInputs to <input[name='is_paid']:checked/> in #filter
|
||||||
|
if isPaidInputs.length is not 2
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check mute_status (default is both active and muted checked)
|
||||||
|
set muteStatusInputs to <input[name='mute_status']:checked/> in #filter
|
||||||
|
if muteStatusInputs.length is not 2
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check description
|
||||||
|
set descInput to #id_description
|
||||||
|
if descInput exists and descInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check date_start
|
||||||
|
set dateStartInput to #id_date_start
|
||||||
|
if dateStartInput exists and dateStartInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check date_end
|
||||||
|
set dateEndInput to #id_date_end
|
||||||
|
if dateEndInput exists and dateEndInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check reference_date_start
|
||||||
|
set refDateStartInput to #id_reference_date_start
|
||||||
|
if refDateStartInput exists and refDateStartInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check reference_date_end
|
||||||
|
set refDateEndInput to #id_reference_date_end
|
||||||
|
if refDateEndInput exists and refDateEndInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check from_amount
|
||||||
|
set fromAmountInput to #id_from_amount
|
||||||
|
if fromAmountInput exists and fromAmountInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check to_amount
|
||||||
|
set toAmountInput to #id_to_amount
|
||||||
|
if toAmountInput exists and toAmountInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check account (TomSelect stores values differently)
|
||||||
|
set accountInput to #id_account
|
||||||
|
if accountInput exists and accountInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check currency
|
||||||
|
set currencyInput to #id_currency
|
||||||
|
if currencyInput exists and currencyInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check category
|
||||||
|
set categoryInput to #id_category
|
||||||
|
if categoryInput exists and categoryInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check tags
|
||||||
|
set tagsInput to #id_tags
|
||||||
|
if tagsInput exists and tagsInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check entities
|
||||||
|
set entitiesInput to #id_entities
|
||||||
|
if entitiesInput exists and entitiesInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show or hide the indicator
|
||||||
|
if hasActiveFilter
|
||||||
|
remove .hidden from #filter-active-indicator
|
||||||
|
else
|
||||||
|
add .hidden to #filter-active-indicator
|
||||||
|
end">
|
||||||
<i class="fa-solid fa-filter fa-fw"></i>
|
<i class="fa-solid fa-filter fa-fw"></i>
|
||||||
|
<span id="filter-active-indicator" class="absolute -top-1 -right-1 w-3 h-3 bg-error rounded-full hidden z-10"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{# Search box #}
|
{# Search box #}
|
||||||
|
|||||||
@@ -52,11 +52,112 @@
|
|||||||
{# Main control bar with filter, search, and ordering #}
|
{# Main control bar with filter, search, and ordering #}
|
||||||
<div class="join w-full">
|
<div class="join w-full">
|
||||||
|
|
||||||
<button class="btn btn-secondary join-item relative" type="button"
|
<button class="btn btn-secondary join-item relative z-1" type="button"
|
||||||
@click="filterOpen = !filterOpen"
|
@click="filterOpen = !filterOpen"
|
||||||
:aria-expanded="filterOpen" id="filter-button"
|
:aria-expanded="filterOpen" id="filter-button"
|
||||||
title="{% translate 'Filter transactions' %}">
|
title="{% translate 'Filter transactions' %}"
|
||||||
|
_="on load or change from #filter
|
||||||
|
-- Check if any filter has a non-default value
|
||||||
|
set hasActiveFilter to false
|
||||||
|
|
||||||
|
-- Check type (default is both IN and EX checked)
|
||||||
|
set typeInputs to <input[name='type']:checked/> in #filter
|
||||||
|
if typeInputs.length is not 2
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check is_paid (default is both 1 and 0 checked)
|
||||||
|
set isPaidInputs to <input[name='is_paid']:checked/> in #filter
|
||||||
|
if isPaidInputs.length is not 2
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check mute_status (default is both active and muted checked)
|
||||||
|
set muteStatusInputs to <input[name='mute_status']:checked/> in #filter
|
||||||
|
if muteStatusInputs.length is not 2
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check description
|
||||||
|
set descInput to #id_description
|
||||||
|
if descInput exists and descInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check date_start
|
||||||
|
set dateStartInput to #id_date_start
|
||||||
|
if dateStartInput exists and dateStartInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check date_end
|
||||||
|
set dateEndInput to #id_date_end
|
||||||
|
if dateEndInput exists and dateEndInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check reference_date_start
|
||||||
|
set refDateStartInput to #id_reference_date_start
|
||||||
|
if refDateStartInput exists and refDateStartInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check reference_date_end
|
||||||
|
set refDateEndInput to #id_reference_date_end
|
||||||
|
if refDateEndInput exists and refDateEndInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check from_amount
|
||||||
|
set fromAmountInput to #id_from_amount
|
||||||
|
if fromAmountInput exists and fromAmountInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check to_amount
|
||||||
|
set toAmountInput to #id_to_amount
|
||||||
|
if toAmountInput exists and toAmountInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check account (TomSelect stores values differently)
|
||||||
|
set accountInput to #id_account
|
||||||
|
if accountInput exists and accountInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check currency
|
||||||
|
set currencyInput to #id_currency
|
||||||
|
if currencyInput exists and currencyInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check category
|
||||||
|
set categoryInput to #id_category
|
||||||
|
if categoryInput exists and categoryInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check tags
|
||||||
|
set tagsInput to #id_tags
|
||||||
|
if tagsInput exists and tagsInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check entities
|
||||||
|
set entitiesInput to #id_entities
|
||||||
|
if entitiesInput exists and entitiesInput.value is not ''
|
||||||
|
set hasActiveFilter to true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show or hide the indicator
|
||||||
|
if hasActiveFilter
|
||||||
|
remove .hidden from #filter-active-indicator
|
||||||
|
else
|
||||||
|
add .hidden to #filter-active-indicator
|
||||||
|
end">
|
||||||
<i class="fa-solid fa-filter fa-fw"></i>
|
<i class="fa-solid fa-filter fa-fw"></i>
|
||||||
|
<span id="filter-active-indicator" class="absolute -top-1 -right-1 w-3 h-3 bg-error rounded-full hidden z-10"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{# Search box #}
|
{# Search box #}
|
||||||
|
|||||||
Reference in New Issue
Block a user