Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Django messages to reuse toast component used by htmx #4385

Merged
merged 4 commits into from
Feb 12, 2025
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
5 changes: 5 additions & 0 deletions hypha/static_src/tailwind/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@
)
10;
}

/* see https://github.com/tailwindlabs/tailwindcss/pull/12128 */
.break-anywhere {
overflow-wrap: anywhere;
}
}
9 changes: 5 additions & 4 deletions hypha/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@
{% include "includes/hijack-bar.html" %}
{% endif %}

{% if messages %}
{% include 'includes/messages.html' %}
{% endif %}

{% block header %}{% endblock header %}

{% block content_wrapper %}
Expand Down Expand Up @@ -166,6 +162,11 @@
{% include "includes/_modal-placeholder.html" %}
{% include "includes/_toast-placeholder.html" %}

{# Display messages from django.contrib.messages as toast #}
{% for message in messages %}
<template x-init="$nextTick(() => {$dispatch('notice', {type: '{{ message.tags }}', text: '{{ message }}'})})"></template>
{% endfor %}

<!-- We still need jQuery for select2, daterangepicker and a few custom scripts. -->
<!-- Please do not add new features that require jQuery! -->
<script src="{% static 'js/vendor/jquery.min.js' %}"></script>
Expand Down
61 changes: 32 additions & 29 deletions hypha/templates/includes/_toast-placeholder.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
{% comment %}
How this works:
- A htmx response responds with either "showMessage" or "messages" "HX-Trigger" event.
- htmx traps the event and create another event for the toast layer.
- htmx traps the event and creates another event for the toast layer.
- The toast layer listens to the event and adds the toast to the list.
- Toasts can be paused on hover and dismissed manually
- Supports different message types with corresponding styles and icons
{% endcomment %}

<!-- Toast layer -->
<script>
function toastHandler() {
"use strict";
const AUTO_HIDE_TIMEOUT = 2500;
const AUTO_HIDE_TIMEOUT = 3000;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give a generous time to reader of the notification.

return {
toasts: [],
visible: [],
Expand Down Expand Up @@ -56,36 +58,28 @@
},
};
}

const createNoticeEvent = (detail) => new CustomEvent("notice", {
detail,
bubbles: true,
cancelable: true,
composed: true
});

htmx.on("showMessage", (e) => {
let message_detail = { type: "success", text: e.detail.value };
dispatchEvent(
new CustomEvent("notice", {
detail: message_detail,
bubbles: true,
cancelable: true,
composed: true,
})
);
dispatchEvent(createNoticeEvent({ type: "success", text: e.detail.value }));
});

htmx.on("messages", (e) => {
e.detail.value.forEach((message) => {
let message_detail = { type: message.tags, text: message.message };
console.log(message_detail);
dispatchEvent(
new CustomEvent("notice", {
detail: message_detail,
bubbles: true,
cancelable: true,
composed: true,
})
);
e.detail.value.forEach(message => {
dispatchEvent(createNoticeEvent({ type: message.tags, text: message.message }));
});
});
</script>

<div
x-data="toastHandler()"
class="flex fixed inset-0 flex-col justify-start items-end px-4 w-screen h-screen pointer-events-none"
class="flex fixed inset-0 z-50 flex-col justify-start items-end px-8 mx-auto w-screen h-screen pointer-events-none max-w-[2200px]"
@notice.window="add($event.detail)"
>
<template x-for="toast of toasts" :key="toast.id">
Expand All @@ -96,30 +90,39 @@
x-show="visible.includes(toast)"
x-transition:enter="transition ease-in duration-200"
x-transition:enter-start="transform opacity-0 translate-y-2"
x-transition:enter-end="transform opacity-100"
x-transition:enter-end="transform opacity-100 translate-y-0"
x-transition:leave="transition ease-out duration-500"
x-transition:leave-start="transform translate-x-0 opacity-100"
x-transition:leave-end="transform translate-x-full opacity-0"
@click="remove(toast.id)"
@mouseenter="pause(toast.id)"
@mouseleave="resume(toast.id)"
class="relative py-3 px-4 mt-4 w-full max-w-full text-sm font-bold text-white rounded-md shadow-xl cursor-pointer sm:w-auto sm:max-w-sm group"
class="relative py-3 px-4 mt-4 w-full max-w-full text-sm font-semibold text-white rounded-md shadow-xl cursor-pointer sm:w-auto sm:max-w-sm break-anywhere hyphens-auto group sm:min-w-64"
:class="{
'bg-gray-500': toast.type === 'debug',
'bg-green-500': toast.type === 'success',
'bg-neutral-500': toast.type === 'debug',
'bg-green-600': toast.type === 'success',
'bg-blue-500': toast.type === 'info',
'bg-orange-500': toast.type === 'warning',
'bg-red-500': toast.type === 'error',
}"
style="pointer-events:all"
>
<div class="flex gap-2 items-center">
<div class="flex gap-4 items-center">
<span x-show="toast.type == 'info'" aria-hidden="true">
{% heroicon_solid "information-circle" size=24 class="inline-block rounded-full" %}
{% heroicon_solid "light-bulb" size=24 class="inline-block rounded-full" %}
</span>
<span x-show="toast.type == 'success'" aria-hidden="true">
{% heroicon_solid "check-circle" size=24 class="inline-block rounded-full" %}
</span>
<span x-show="toast.type == 'warning'" aria-hidden="true">
{% heroicon_solid "exclamation-circle" size=24 class="inline-block rounded-full" %}
</span>
<span x-show="toast.type == 'error'" aria-hidden="true">
{% heroicon_solid "exclamation-triangle" size=24 class="inline-block rounded-full" %}
</span>
<span x-show="toast.type == 'debug'" aria-hidden="true">
{% heroicon_solid "wrench" size=24 class="inline-block rounded-full" %}
</span>
<span x-text="toast.text"></span>
</div>
<button class="absolute -top-3 -left-3 invisible p-1 transition-all group-hover:visible">
Expand Down
37 changes: 0 additions & 37 deletions hypha/templates/includes/message_item.html

This file was deleted.

6 changes: 0 additions & 6 deletions hypha/templates/includes/messages.html

This file was deleted.

Loading