Skip to content

Commit

Permalink
Proof of concept Lit notification element
Browse files Browse the repository at this point in the history
  • Loading branch information
agjohnson committed Mar 11, 2024
1 parent 90e0895 commit 5d3d6fc
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 61 deletions.
89 changes: 45 additions & 44 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"lato-font": "^3.0.0",
"less": "^4.2.0",
"less-loader": "^11.1.3",
"lit": "^3.1.2",
"matchdep": "~2.0.0",
"mini-css-extract-plugin": "^2.7.6",
"prettier": "^3.0.3",
Expand Down
20 changes: 4 additions & 16 deletions readthedocsext/theme/templates/includes/utils/messages.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,10 @@
page content pane.
{% endcomment %}

{% comment %}
``user_notifications`` comes from a Context Processor.
We need to use a CustomUser to have access to "user.notifications"
See https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-AUTH_USER_MODEL
{% endcomment %}
{% if user_notifications %}
{% for notification in user_notifications %}
<div class="ui message">
{% comment %}
Add this Xmark here once we implement dismissing notifications.
<i class="fa-duotone fa-circle-xmark close icon"></i>
{% endcomment %}
{{ notification.get_message.get_rendered_body|safe }}
</div>
{% endfor %}
{% endif %}
<rtd-notification-list
url="{% url "users-notifications-list" request.user.username %}"
csrf-token="{{ csrf_token }}">
</rtd-notification-list>

{% if messages %}
{% for message in messages %}
Expand Down
3 changes: 2 additions & 1 deletion src/js/modules/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as popupcards from "./popupcards";
import * as header from "./header";
import * as filter from "./filter";
import * as notifications from "./notifications";

export { popupcards, header, filter };
export { popupcards, header, filter, notifications };
92 changes: 92 additions & 0 deletions src/js/modules/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { LitElement, css, html, nothing } from "lit";
import {repeat} from 'lit/directives/repeat.js';
import {when} from 'lit/directives/when.js';
import {classMap} from 'lit/directives/class-map.js';
import {unsafeHTML} from 'lit/directives/unsafe-html.js';

export class NotificationList extends LitElement {
static properties = {
url: {type: String},
csrfToken: {type: String, attribute: "csrf-token"},
notifications: {state: true},
finished: {state: true, type: Boolean},
};

// Use light DOM with inherited styles instead of shadow DOM
createRenderRoot() {
return this;
}

fetchNotifications() {
if (!this.url || this.finished) {
return;
}
fetch(this.url).then((response) => {
response.json().then((data) => {
if (data.results) {
this.notifications = data.results;
}
});
this.finished = true;
});
}

render() {
// Trigger async notification fetch
this.fetchNotifications();

if (this.notifications && this.notifications.length > 0) {
return html`
<div class="ui vertical relaxed list">
${repeat(
this.notifications,
(notification) => notification.id,
(notification, index) => {
return this.renderNotification(notification);
}
)}
</div>
`;
} else {
return nothing;
}
}

renderNotification(notification) {
return html`
<div class="ui ${notification.message.type} message">
${when(notification.dismissable, () => html`
<i class="fas fa-xmark close inline icon" @click=${{handleEvent: () => this.dismissNotification(notification), once: true}}></i>
`)}
<div class="header">
<i class="fad ${notification.message.icon_classes} icon"></i>
${unsafeHTML(notification.message.header)}
</div>
${unsafeHTML(notification.message.body)}
</div>
`
}

dismissNotification(notification) {
console.debug("Dismissing notification:", notification.id);
const options = {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": this.csrfToken,
},
body: {
state: "dismissed",
},
};
fetch(notification._links._self, options).then((response) => {
console.log(response);
// TODO error catch response
response.json().then((data) => {
console.log(data);
});
});
}
}

customElements.define("rtd-notification-list", NotificationList);

0 comments on commit 5d3d6fc

Please sign in to comment.