diff --git a/hypha/apply/activity/context_processors.py b/hypha/apply/activity/context_processors.py index 0ce63073fcf61f5eb472298c986193fa8659eee2..6f94d6b9346ae288ed61d56abe7ee857f7c0195a 100644 --- a/hypha/apply/activity/context_processors.py +++ b/hypha/apply/activity/context_processors.py @@ -3,6 +3,6 @@ from .models import Activity def notification_context(request): context_data = dict() - if request.user.is_authenticated: - context_data['latest_notifications'] = Activity.objects.filter(user=request.user).order_by('-timestamp')[:5] + if request.user.is_authenticated and request.user.is_apply_staff: + context_data['latest_notifications'] = Activity.objects.all().order_by('-timestamp')[:5] return context_data diff --git a/hypha/apply/activity/filters.py b/hypha/apply/activity/filters.py index 73391af450c0a301ff73ef078572e9d68898854c..899c5d5f533e0a77f8afca289760c49f2cbfcba6 100644 --- a/hypha/apply/activity/filters.py +++ b/hypha/apply/activity/filters.py @@ -1,13 +1,43 @@ +from datetime import timedelta + import django_filters +from django.utils.timezone import now +from django.utils.translation import gettext_lazy as _ +from django_filters.filters import DateRangeFilter, _truncate from .models import Activity class NotificationFilter(django_filters.FilterSet): + timestamp_choices = [ + ('today', _('Today')), + ('yesterday', _('Yesterday')), + ('week', _('Past 7 days')), + ('month', _('This month')) + ] + timestamp_filters = { + 'today': lambda qs, name: qs.filter(**{ + '%s__year' % name: now().year, + '%s__month' % name: now().month, + '%s__day' % name: now().day + }), + 'yesterday': lambda qs, name: qs.filter(**{ + '%s__year' % name: (now() - timedelta(days=1)).year, + '%s__month' % name: (now() - timedelta(days=1)).month, + '%s__day' % name: (now() - timedelta(days=1)).day, + }), + 'week': lambda qs, name: qs.filter(**{ + '%s__gte' % name: _truncate(now() - timedelta(days=7)), + '%s__lt' % name: _truncate(now() + timedelta(days=1)), + }), + 'month': lambda qs, name: qs.filter(**{ + '%s__year' % name: now().year, + '%s__month' % name: now().month + }) + } + + date = DateRangeFilter(field_name='timestamp', choices=timestamp_choices, filters=timestamp_filters) class Meta: model = Activity - fields = { - 'timestamp', - 'source_content_type', - } + fields = {} diff --git a/hypha/apply/activity/templates/activity/notifications.html b/hypha/apply/activity/templates/activity/notifications.html index f216ae4205b94773ff3fb1b15384d4a8ac068e84..068a0a6c8181bef0469f983d7eb6f67298178552 100644 --- a/hypha/apply/activity/templates/activity/notifications.html +++ b/hypha/apply/activity/templates/activity/notifications.html @@ -4,7 +4,14 @@ {% block content %} <div class="admin-bar"> <div class="admin-bar__inner"> - <h1 class="gamma heading heading--no-margin heading--bold">{% trans "Notifications" %}</h1> + <div class="admin-bar__inner--with-button"> + <h1 class="gamma heading heading--no-margin heading--bold">{% trans "Notifications" %}</h1> + <form class="form notification__filters" method="get"> + {{ filter.form.as_p }} + <button class="button button--primary" type="submit" value="Filter">{% trans "Filter" %}</button> + </form> + </div> + <div class="tabs js-tabs"> <div class="tabs__container"> <a class="tab__item" href="#comments" data-tab="tab-1"> @@ -22,54 +29,40 @@ <div class="wrapper wrapper--large wrapper--tabs js-tabs-content"> {# Tab 1 #} <div class="tabs__content" id="tab-1"> -<!-- WIP Filters --> -<!-- <div class="filters {% if filter_classes %}{{filter_classes}}{% endif %}">--> -<!-- <div class="filters__header">--> -<!-- <button class="filters__button js-clear-filters">{% trans "Clear" %}</button>--> -<!-- <div>{% trans "Filter by" %}</div>--> -<!-- <button class="filters__button js-close-filters">{% trans "Close" %}</button>--> -<!-- </div>--> - -<!-- <form action="{{ filter_action }}" method="get" class="form form--filters js-filter-form">--> -<!-- <ul class="form__filters select2">--> -<!-- {{ filter.form.as_ul }}--> -<!-- <li>--> -<!-- <button class="button button--primary" type="submit" value="Filter">{% trans "Filter" %}</button>--> -<!-- </li>--> -<!-- </ul>--> -<!-- </form>--> -<!-- </div>--> - - {% for comment in comments %} - <div class="feed__item feed__item--comment"> - <div class="feed__pre-content"> - <p class="feed__label feed__label--comment">{{ comment.source_content_type.name|source_type }}</p> - </div> - <div class="feed__content js-feed-content"> - <div class="feed__meta js-feed-meta"> - <p class="feed__meta-item"><a href="{{ comment.source.get_absolute_url }}">{{ comment.source.title|capfirst|truncatechars:15 }}</a> - : {{ comment.user }} made a comment – {{ comment.timestamp|date:"SHORT_DATETIME_FORMAT" }}</p> + {% for activity in object_list %} + {% if activity.type == 'comment' %} + <div class="feed__item feed__item--comment"> + <div class="feed__pre-content"> + <p class="feed__label feed__label--comment">{{ activity.source_content_type.name|source_type }}</p> + </div> + <div class="feed__content js-feed-content"> + <div class="feed__meta js-feed-meta"> + <p class="feed__meta-item"><a href="{{ activity.source.get_absolute_url }}">{{ activity.source.title|capfirst|truncatechars:15 }}</a> + : {{ activity.user }} made a comment – {{ activity.timestamp|date:"SHORT_DATETIME_FORMAT" }}</p> + </div> + </div> </div> - </div> - </div> + {% endif %} {% endfor %} </div> {# Tab 2 #} <div class="tabs__content" id="tab-2"> - {% for action in actions %} - <div class="feed__item feed__item--action"> - <div class="feed__pre-content"> - <p class="feed__label feed__label--action">{{ action.source_content_type.name|source_type }}</p> - </div> - <div class="feed__content js-feed-content"> - <div class="feed__meta js-feed-meta"> - <p class="feed__meta-item"><a href="{{ action.source.get_absolute_url }}">{{ action.source.title|capfirst|truncatechars:15 }}</a> - : {{ action.message }} {% if action.related_object %}<a href="{{ action.related_object.get_absolute_url }}">{{ action.related_object|model_verbose_name }}</a>{% endif %} - – {{ action.timestamp|date:"SHORT_DATETIME_FORMAT" }}</p> + {% for activity in object_list %} + {% if activity.type == 'action' %} + <div class="feed__item feed__item--action"> + <div class="feed__pre-content"> + <p class="feed__label feed__label--action">{{ activity.source_content_type.name|source_type }}</p> + </div> + <div class="feed__content js-feed-content"> + <div class="feed__meta js-feed-meta"> + <p class="feed__meta-item"><a href="{{ activity.source.get_absolute_url }}">{{ activity.source.title|capfirst|truncatechars:15 }}</a> + : {{ activity.message }} {% if activity.related_object %}<a href="{{ activity.related_object.get_absolute_url }}">{{ activity.related_object|model_verbose_name }}</a>{% endif %} + – {{ activity.timestamp|date:"SHORT_DATETIME_FORMAT" }}</p> + </div> </div> </div> - </div> - {% endfor %} + {% endif %} + {% endfor %} </div> </div> diff --git a/hypha/apply/activity/views.py b/hypha/apply/activity/views.py index 67ab9604e71e57a38095166478d724675893c242..09253b5bac50bb8bcafa88bfaa654796b2b2ade9 100644 --- a/hypha/apply/activity/views.py +++ b/hypha/apply/activity/views.py @@ -2,9 +2,10 @@ from django.utils import timezone from django.utils.decorators import method_decorator from django.views.generic import CreateView, ListView -from hypha.apply.users.decorators import login_required +from hypha.apply.users.decorators import staff_required from hypha.apply.utils.views import DelegatedViewMixin +from .filters import NotificationFilter from .forms import CommentForm from .messaging import MESSAGES, messenger from .models import COMMENT, Activity @@ -61,32 +62,19 @@ class CommentFormView(DelegatedViewMixin, CreateView): return kwargs -@method_decorator(login_required, name='dispatch') +@method_decorator(staff_required, name='dispatch') class NotificationsView(ListView): model = Activity template_name = 'activity/notifications.html' + filterset_class = NotificationFilter + + def get_queryset(self): + # List only last 30 days' activities + queryset = Activity.objects.filter(timestamp__gte=(timezone.now() - timezone.timedelta(days=30))) + self.filterset = self.filterset_class(self.request.GET, queryset=queryset) + return self.filterset.qs.distinct().order_by('-timestamp') def get_context_data(self, *, object_list=None, **kwargs): context = super(NotificationsView, self).get_context_data() - user = self.request.user - comments = Activity.comments.all() - actions = Activity.actions.all() - - # Getting issues with source's reverse relationship - # if user.is_applicant or user.is_partner: - # context['comments'] = comments.filter(source__user=user).order_by('-timestamp') - # context['actions'] = actions.filter(source__user=user).order_by('-timestamp') - # elif user.is_reviewer: - # reviewer_submissions = ApplicationSubmission.objects.filter(reviewers=user).values_list("id", flat=True) - # context['comments'] = comments.filter(source_object_id__in=reviewer_submissions).order_by('-timestamp') - # context['actions'] = actions.filter(source_object_id__in=reviewer_submissions).order_by('-timestamp') - - if user.is_apply_staff or user.is_apply_staff_admin: - context['comments'] = comments.all().order_by('-timestamp') - context['actions'] = actions.all().order_by('-timestamp') - else: - context['comments'] = comments.filter(user=user).order_by('-timestamp') - context['actions'] = actions.filter(user=user).order_by('-timestamp') - # WIP Filters - # context['filter'] = NotificationFilter(self.request.GET, queryset=self.get_queryset()) + context['filter'] = self.filterset return context diff --git a/hypha/static_src/src/sass/apply/components/_activity-notifications.scss b/hypha/static_src/src/sass/apply/components/_activity-notifications.scss index 9cdc26e2de6bb3adde2576c44e1f2164d39c6106..5afe45446e0a1b68c33bc90cef38993d23f91a43 100644 --- a/hypha/static_src/src/sass/apply/components/_activity-notifications.scss +++ b/hypha/static_src/src/sass/apply/components/_activity-notifications.scss @@ -40,3 +40,24 @@ .show { display:block; } + + +.notification { + + &__filters { + display: flex; + align-items: center; + padding: 4px; + justify-content: space-between; + + p { + font-weight: 520; + padding-right: 10px; + } + + select { + padding-right: 1em; + } + + } +} diff --git a/hypha/templates/base-apply.html b/hypha/templates/base-apply.html index c67b94e85295999ce301a5d21485165954e67000..f9706cdd2e500d8a7a3177f1df6e93ddf0946252 100644 --- a/hypha/templates/base-apply.html +++ b/hypha/templates/base-apply.html @@ -1,4 +1,4 @@ -{% load i18n static wagtailuserbar wagtailcore_tags wagtailimages_tags navigation_tags util_tags hijack cookieconsent_tags activity_tags %}<!doctype html> +{% load i18n static wagtailuserbar wagtailcore_tags wagtailimages_tags navigation_tags util_tags hijack cookieconsent_tags activity_tags apply_tags %}<!doctype html> {% wagtail_site as current_site %} <html class="no-js" lang="en"> <head> @@ -114,9 +114,10 @@ <p><b>Notifications</b></p> {% for notification in latest_notifications %} <p class="dropdown-item"> - <span class="source-label">{{ notification.source_content_type.name|source_type }}</span> + <span><b>{{ notification.source_content_type.name|source_type }}</b></span> <a href="{{ notification.source.get_absolute_url }}">{{ notification.source.title|capfirst|truncatechars:15 }}</a> - : {{ notification.user }} {% ifequal notification.type 'comment' %}made a comment{% else %} {{ notification.message|safe }}{% endifequal %} + : {{ notification.user }} {% ifequal notification.type 'comment' %}made a comment{% else %} {{ notification.message|safe }} + {% if notification.related_object %}<a href="{{ notification.related_object.get_absolute_url }}">{{ notification.related_object|model_verbose_name }}</a>{% endif %}{% endifequal %} </p> {% endfor %} <p class="show-all"><a href="{% url "activity:notifications" %}">Show All</a></p>