Skip to content

Commit

Permalink
Adding filter for notification recipient in notifications admin page;
Browse files Browse the repository at this point in the history
Adding test for the filter
  • Loading branch information
Fancien committed Nov 6, 2023
1 parent 514dc44 commit a9c0ece
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 17 deletions.
6 changes: 5 additions & 1 deletion notification/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,16 @@ def api_get_notifications(request):
notifications_list = Notification.objects.filter(
dispatch_in_app=True,
)

if request.GET.get("show_dismissed") != "true":
notifications_list = notifications_list.filter(dismissed=False)
if request.GET.get("as_admin") != "true":
notifications_list = notifications_list.filter(recipient__pk=request.user.pk)
elif request.GET.get("recipient", ""):
notifications_list = notifications_list.filter(
recipient__pk=request.GET.get("recipient")
)

breakpoint()
return jsonify(notifications_list.all())


Expand Down
15 changes: 15 additions & 0 deletions notification/templates/notification/notification_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,24 @@ <h1 class="display-4">Notifications</h1>
</div>
</div>

{% if form %}
<div class="row mt-4">
<div class="card col">
<div class="card-body">
<h2 class="card-title">Filter by user</h2>
{% include '_includes/forms.html' with method='get' %}
</div>
</div>
</div>
{% endif %}


<div id="react-notifications"
data-show-dismissed="{{ show_dismissed | lower }}"
data-show-dismiss-column="{% if not admin %}true{% endif %}"
{% if admin %}
data-recipient-filter="{{ recipient_filter }}"
{% endif %}
data-show-recipient-column="{{ admin | lower }}"
></div>

Expand Down
3 changes: 0 additions & 3 deletions notification/tests.py

This file was deleted.

2 changes: 1 addition & 1 deletion notification/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def _method(
verb=i % 2 == 0 and NotificationVerb.start or NotificationVerb.end,
content_object=content_object, # should be a dataset but not tested yet
)
return Notification.objects.all()
return Notification.objects.filter(recipient__pk=user.pk).all()

return _method

Expand Down
30 changes: 30 additions & 0 deletions notification/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,36 @@ def test_api_get_notifications_wrong_user(
is_valid_api_response(json_response, 0)


def test_api_get_notifications_admin_with_recipient(
client: "Client",
user_normal: "settings.AUTH_USER_MODEL",
user_staff: "settings.AUTH_USER_MODEL",
notifications_for_user: callable,
):
"""
:param client:
:param user_normal:
:param user_staff:
:param notifications_for_user:
:return:
"""
notifications = notifications_for_user(user_normal)
unwanted_notifications = notifications_for_user(user_staff)

assert client.login(
username=user_staff.username, password="password"
), "Login failed"

json_response = client.get(
reverse("api_notifications"), {"as_admin": "true", "recipient": user_normal.pk}
)
data = is_valid_api_response(json_response, len(notifications))
received_ids = [n["id"] for n in data]
for notification in unwanted_notifications:
assert notification.to_json()["id"] not in received_ids


def test_api_get_notifications_admin(
client: "Client",
user_normal: "settings.AUTH_USER_MODEL",
Expand Down
1 change: 1 addition & 0 deletions notification/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def get_context_data(self, *, object_list=None, **kwargs):
if "pk" in self.kwargs:
user = get_object_or_404(User, pk=self.kwargs["pk"])
submit_url = reverse("notifications_admin_for_user", kwargs={"pk": user.pk})
context["recipient_filter"] = user.pk
else:
submit_url = reverse("notifications_admin")
context["submit_url"] = submit_url
Expand Down
5 changes: 5 additions & 0 deletions web/static/vendor/components/notification/index_notif.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import {NotificationList} from "./notifications_list";
const notifDivDOM = document.getElementById("react-notifications");
const csrfTokenNode: HTMLInputElement | null = document.querySelector<HTMLInputElement>("input[name=csrfmiddlewaretoken]");
if (notifDivDOM && csrfTokenNode){
const recipientFilter = notifDivDOM.dataset.recipientFilter ?
parseInt(notifDivDOM.dataset.recipientFilter, 10) :
null;

const root = createRoot(notifDivDOM);
root.render(
<React.StrictMode>
<NotificationList
showDismissed={notifDivDOM.dataset.showDismissed === "true"}
showRecipientColumn={notifDivDOM.dataset.showRecipientColumn === "true"}
showDismissColumn={notifDivDOM.dataset.showDismissColumn === "true"}
recipientFilter={recipientFilter}
csrf={csrfTokenNode.value}
/>
</React.StrictMode>
Expand Down
29 changes: 17 additions & 12 deletions web/static/vendor/components/notification/notifications_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const API_URL_DISMISS_ALL_NOTIFICATION = "/notifications/api/dismiss-all";
type NotificationListProps = {
showDismissed: boolean,
showRecipientColumn: boolean,
showDismissColumn: boolean
showDismissColumn: boolean,
recipientFilter: number | null,
csrf: string,
}

Expand All @@ -20,11 +21,12 @@ type NotificationListProps = {
* @param showDismissed - If true, the list will display dismissed notifications
* @param showRecipientColumn - If true, the list will display the recipient column
* @param showDismissColumn - If true, the list will display the dismiss column
* @param recipientFilter - If not null, the list will only display notifications for the given recipient
* @param csrf - CSRF token
*
* @return - The list of notifications divided into cards by content type
*/
export const NotificationList = ({showDismissed, showRecipientColumn, showDismissColumn, csrf}: NotificationListProps) => {
export const NotificationList = ({showDismissed, showRecipientColumn, showDismissColumn, recipientFilter, csrf}: NotificationListProps) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [notifications, setNotifications] = useState<Record<string, CustomType.Notification[]>>({});

Expand All @@ -43,16 +45,19 @@ export const NotificationList = ({showDismissed, showRecipientColumn, showDismis

// Fetch notifications from the API
useEffect(() => {
fetch(
`${API_URL_NOTIFICATIONS_LIST}?show_dismissed=${showDismissed}&as_admin=${showRecipientColumn}`,
).then(response => response.json() as Promise<CustomType.NotifApiResponse>
).then(json => {
setNotifications(groupNotifications(json.data));
setIsLoading(false);
}).catch(error => {
console.error(error);
});
}, [showDismissed, showRecipientColumn]);
let url = `${API_URL_NOTIFICATIONS_LIST}?show_dismissed=${showDismissed}&as_admin=${showRecipientColumn}`;
if (recipientFilter) {
url += `&recipient=${recipientFilter}`;
}
fetch(url)
.then(response => response.json() as Promise<CustomType.NotifApiResponse>)
.then(json => {
setNotifications(groupNotifications(json.data));
setIsLoading(false);
}).catch(error => {
console.error(error);
});
}, [showDismissed, showRecipientColumn, recipientFilter]);

/**
* Method to dismiss a notification
Expand Down

0 comments on commit a9c0ece

Please sign in to comment.