Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ download-esm-modules: ## Download ECMAScript modules for the project
download-esm @github/relative-time-element $(JS_ESM_DIR)
download-esm @github/filter-input-element $(JS_ESM_DIR)
download-esm choices.js $(JS_ESM_DIR)
download-esm cally $(JS_ESM_DIR)


.cache/tandem: ## Install tandem, a tool for running multiple commands in parallel
Expand All @@ -100,6 +101,4 @@ download-esm-modules: ## Download ECMAScript modules for the project
cp node_modules/htmx.org/dist/ext/multi-swap.js $(JS_VENDOR_DIR)/htmx-ext-multi-swap.min.js
cp node_modules/alpinejs/dist/cdn.min.js $(JS_VENDOR_DIR)/alpine.min.js
cp node_modules/@alpinejs/focus/dist/cdn.min.js $(JS_VENDOR_DIR)/alpine-focus.min.js
cp node_modules/daterangepicker/moment.min.js $(JS_VENDOR_DIR)/moment.min.js
cp node_modules/daterangepicker/daterangepicker.js $(JS_VENDOR_DIR)/daterangepicker.min.js
@touch $@
Original file line number Diff line number Diff line change
Expand Up @@ -103,59 +103,49 @@ <h2 class="section-header">{{ heading }}</h2>
</ul>
{% enddropdown_menu %}
{% else %}
<div id="{{ field_name }}"
class="flex justify-between items-center py-1 w-full font-medium border cursor-pointer md:border-none text-base-content/80 ps-2 pe-2 md:hover:bg-transparent md:hover:text-primary hover:bg-base-200"
data-field-name="{{ field_name }}" data-filter-list>
{{ field.label }}
{% heroicon_micro attributes.icon|default:"chevron-down" aria_hidden="true" size="16" class="hidden md:inline-block size-4 ms-0.5" %}
</div>
{% dropdown_menu title=field.label heading=field|get_dropdown_heading position="right" %}
<calendar-range class="mx-auto cally" onchange="updateURL(this.value, '{{field_name}}')" data-field-name='{{field_name}}'>
{% heroicon_micro "chevron-left" aria_label="Previous" slot="previous" aria_hidden=true size=18 %}
{% heroicon_micro "chevron-right" aria_label="Next" slot="next" aria_hidden=true size=18 %}
<calendar-month></calendar-month>
</calendar-range>
{% enddropdown_menu %}

<script defer src="{% static 'js/vendor/moment.min.js' %}"></script>
<script defer src="{% static 'js/vendor/daterangepicker.min.js' %}"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
function updateURL(paramStart, paramEnd, startDate, endDate) {
let url = new URL(window.location);
if (startDate) {
url.searchParams.set(paramStart, startDate);
} else {
url.searchParams.delete(paramStart);
}
/**
* Update the current URL with the date params and reload the page
*
* @param {string} dateRange - the date range in the format of `YYYY-MM-DD/YYYY-MM-DD`
* @param {string} fieldName - the field being used as a query param
*/
function updateURL(dateRange, fieldName) {
const [startDate, endDate] = dateRange.split('/');
const paramStart = `${fieldName}_after`
const paramEnd = `${fieldName}_before`

if (endDate) {
url.searchParams.set(paramEnd, endDate);
} else {
url.searchParams.delete(paramEnd);
}
window.history.pushState({}, '', url);
location.reload(); // Reload to apply the filter
}
let url = new URL(window.location);
url.searchParams.set(paramStart, startDate);
url.searchParams.set(paramEnd, endDate);

window.history.pushState({}, '', url);
location.reload(); // Reload to apply the filter
}

var fieldName = "{{ field_name }}"; // Django variable inside JS
let dateLink = $("#{{ field_name }}");
document.addEventListener("DOMContentLoaded", function () {
// Get all date pickers and set their initial range values based on the URL params
document.querySelectorAll(".cally").forEach((datepicker) => {
const fieldName = datepicker.getAttribute("data-field-name");

var start = moment().subtract(29, 'days');
var end = moment();
const params = new URL(window.location).searchParams;

const startDate = params.get(`${fieldName}_after`);
const endDate = params.get(`${fieldName}_before`);

dateLink.daterangepicker({
startDate: start,
endDate: end,
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
if (startDate && endDate) {
datepicker.value = `${startDate}/${endDate}`
}
}, function(start, end) {
let formattedStart = start.format('YYYY-MM-DD');
let formattedEnd = end.format('YYYY-MM-DD');
dateLink.textContent = formattedStart + ' - ' + formattedEnd;
updateURL(fieldName + "_after", fieldName + "_before", formattedStart, formattedEnd);
});
});
})
})
</script>
{% endif %}
</nav>
Expand Down
75 changes: 31 additions & 44 deletions hypha/apply/funds/templates/submissions/all.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
hx-target="#main"
hx-push-url="true"
hx-swap="outerHTML transition:true"
name="querySubmissions"
>

{% dropdown_menu title="Filters" heading="Filter submissions" %}
Expand Down Expand Up @@ -322,19 +323,21 @@
x-show="!showSelectedSubmissions"
class="flex flex-wrap gap-2 items-center menu-filters"
>
<div id="filtersubmitted" aria-label="Filter by Submitted" class="flex items-center" data-query="submitted">
<button class="flex justify-between items-center py-1 w-full font-medium border cursor-pointer md:p-0 md:border-none text-base-content/80 ps-2 pe-2 md:pe-4 md:hover:bg-transparent md:hover:text-primary hover:bg-base-200">
{% trans "Submitted" %}
{% heroicon_mini "chevron-down" aria_hidden="true" width=18 height=18 class="hidden md:inline-block" %}
</button>
</div>
{% dropdown_menu title="Submitted" heading="Filter by submitted date(s)" %}
<calendar-range class="mx-auto cally" {% if selected_submitted_date %}value="{{selected_submitted_date}}"{% endif %} onchange="setDateFromPicker(this.value, 'submitted')">
{% heroicon_micro "chevron-left" aria_label="Previous" slot="previous" aria_hidden=true size=18 %}
{% heroicon_micro "chevron-right" aria_label="Next" slot="next" aria_hidden=true size=18 %}
<calendar-month></calendar-month>
</calendar-range>
{% enddropdown_menu %}

<div id="filterupdated" aria-label="Filter by Updated" class="flex items-center" data-query="updated">
<button class="flex justify-between items-center py-1 w-full font-medium border cursor-pointer md:p-0 md:border-none text-base-content/80 ps-2 pe-2 md:pe-4 md:hover:bg-transparent md:hover:text-primary hover:bg-base-200">
{% trans "Updated" %}
{% heroicon_mini "chevron-down" aria_hidden="true" width=18 height=18 class="hidden md:inline-block" %}
</button>
</div>
{% dropdown_menu title="Updated" heading="Filter by updated date(s)" %}
<calendar-range class="mx-auto cally" {% if selected_updated_date %}value="{{selected_updated_date}}"{% endif %} onchange="setDateFromPicker(this.value, 'updated')">
{% heroicon_micro "chevron-left" aria_label="Previous" slot="previous" aria_hidden=true size=18 %}
{% heroicon_micro "chevron-right" aria_label="Next" slot="next" aria_hidden=true size=18 %}
<calendar-month></calendar-month>
</calendar-range>
{% enddropdown_menu %}

{% dropdown_menu title="Status" heading="Filter by current status" enable_search=True %}
<ul
Expand Down Expand Up @@ -530,38 +533,22 @@ <h2 class='mb-2 text-2xl card-title'>{% trans "No results matched your search" %
{% endspaceless %}{% endblock content %}

{% block extra_js %}
<!-- Datetime picker-->
<script src="{% static 'js/vendor/moment.min.js' %}"></script>
<script src="{% static 'js/vendor/daterangepicker.min.js' %}"></script>
<script>
// Date Range Picker
// ---------------------------------------------
htmx.onLoad(function() {
var start = moment().subtract(29, 'days');
var end = moment();

// Add the picker for all elements that need it
$.each(['#filterupdated', '#filtersubmitted'], (index, element) => {
$(element).daterangepicker({
startDate: start,
endDate: end,
ranges: {
'{% trans "Today" %}': [moment(), moment()],
'{% trans "Yesterday" %}': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'{% trans "Last 7 Days" %}': [moment().subtract(6, 'days'), moment()],
'{% trans "Last 30 Days" %}': [moment().subtract(29, 'days'), moment()],
'{% trans "This Month" %}': [moment().startOf('month'), moment().endOf('month')],
'{% trans "Last Month" %}': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
});

var query = $(element).attr("data-query");

$(element).on('apply.daterangepicker', function(ev, picker) {
$('#search-navbar').val(`${query}:>=${picker.startDate.format('YYYY-MM-DD')} ${query}:<=${picker.endDate.format('YYYY-MM-DD')}`);
$('#search-navbar').closest('form').trigger('submit');
});
})
});
/**
* Change the value of the query bar based on the provided date range and query param,
* then submit the query
*
* @param {string} dateRange - the date range in the format of `YYYY-MM-DD/YYYY-MM-DD`
* @param {string} query - the param to be used in the search bar. ie. `updated`
*
*/
function setDateFromPicker(dateRange, query) {
const searchBar = document.getElementById("search-navbar");
let [startDate, endDate] = dateRange.split("/");

// Update searchbar value and submit the query
searchBar.value = `${query}:>=${startDate} ${query}:<=${endDate}`
document.querySubmissions.submit()
}
</script>
{% endblock %}
8 changes: 6 additions & 2 deletions hypha/apply/funds/views/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ def submissions_all(
)
selected_sort = request.GET.get("sort")
page = request.GET.get("page", 1)
selected_updated_date = None
selected_submitted_date = None

can_view_archives = permissions.can_view_archived_submissions(request.user)
can_access_drafts = permissions.can_access_drafts(request.user)
Expand Down Expand Up @@ -143,12 +145,12 @@ def submissions_all(
qs = qs.exclude_draft()

if "submitted" in search_filters:
qs = apply_date_filter(
qs, selected_submitted_date = apply_date_filter(
qs=qs, field="submit_time", values=search_filters["submitted"]
)

if "updated" in search_filters:
qs = apply_date_filter(
qs, selected_updated_date = apply_date_filter(
qs=qs, field="last_update", values=search_filters["updated"]
)

Expand Down Expand Up @@ -323,6 +325,8 @@ def submissions_all(
"selected_reviewers": selected_reviewers,
"selected_meta_terms": selected_meta_terms,
"selected_category_options": selected_category_options,
"selected_updated_date": selected_updated_date,
"selected_submitted_date": selected_submitted_date,
"status_counts": status_counts,
"sort_options": sort_options,
"selected_sort": selected_sort,
Expand Down
17 changes: 13 additions & 4 deletions hypha/apply/search/filters.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import datetime as dt
from typing import Tuple

from django.db.models import Q
from django.db.models import Q, QuerySet

from hypha.apply.search.query_parser import tokenize_date_filter_value


def apply_date_filter(qs, field, values):
"""Given a queryset, a field name, and a list of date strings, filter the queryset."""
def apply_date_filter(qs, field, values) -> Tuple[QuerySet, str]:
"""Given a queryset, a field name, and a list of date strings, filter the queryset.

Returns:
tuple: the filtered queryset and the parsed date range in the format of `[YYYY-MM-DD start date]/[YYYY-MM-DD end date]`

"""
q_obj = Q()

date_range = []

for date_str in values:
tokens = tokenize_date_filter_value(date_str)
date_range.append(f"{tokens[-3]}-{tokens[-2]:02}-{tokens[-1]:02}")

if q := date_filter_tokens_to_q_obj(tokens=tokens, field=field):
q_obj &= q
else:
return qs.none()

return qs.filter(q_obj)
return (qs.filter(q_obj), "/".join(date_range))


def date_filter_tokens_to_q_obj(tokens: list, field: str) -> Q:
Expand Down
7 changes: 7 additions & 0 deletions hypha/static_src/javascript/esm/cally-0-8-0.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions hypha/static_src/javascript/esm/choices.js-11-1-0.js

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading