1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 | /**
* notfications Component
*
* generates a HTML component which will be used to display notifications
*/
import { getAuth } from "firebase/auth";
import { app } from "../handlers/firebaseHandler";
import { collection, query, where, onSnapshot, setDoc, orderBy, limit } from "firebase/firestore";
import { db } from "../handlers/databaseHandler";
import { mutationObserver } from "../handlers/mutationObserver";
import { notify } from "../functions/toasts";
const auth = getAuth(app);
export const notificationsComponent = () => {
mutationObserver('notificationsButton', () => {
const notifications = document.getElementById('notificationsButton');
const handleLoginContainer = document.getElementById("handleLoginContainer");
if (notifications && handleLoginContainer) {
const user = auth.currentUser?.uid;
if (user) {
const notificationsRef = collection(db, "userProfiles", user, "notifications");
const notificationsQuery = query(notificationsRef, where("read", "==", false));
notifications.classList.add('has-notifications');
onSnapshot(notificationsQuery, (snapshot) => {
if (snapshot.size > 0) {
notifications.classList.add('has-notifications');
// Notifications which are not read and also not shown are shown
snapshot.forEach((doc) => {
const notification = doc.data();
if (!notification.shown) {
notify({ title: notification.title, body: notification.body });
setDoc(doc.ref, { shown: true }, { merge: true });
}
});
} else {
notifications.classList.remove('has-notifications');
}
});
}
}
});
}
export const notificationDropdownComponent = () => {
mutationObserver('notificationsButton', () => {
const handleLoginContainer = document.getElementById("handleLoginContainer");
const dropdownContainer = document.createElement("div");
dropdownContainer.id = "notificationDropdown";
dropdownContainer.classList.add("dropdown");
dropdownContainer.style.display = "none";
const dropdownContents = document.createElement("div");
dropdownContents.style.maxHeight = "300px";
dropdownContents.style.overflowY = "auto";
dropdownContainer.appendChild(dropdownContents);
if (handleLoginContainer) {
const user = auth.currentUser?.uid;
if (user) {
const allNotificationsQuery = query(collection(db, "userProfiles", user, "notifications"), orderBy("timestamp", "desc"), limit(50));
onSnapshot(allNotificationsQuery, (snapshot) => {
const snapshotData = snapshot.docs.map((doc) => {
const data = doc.data();
data.ref = doc.ref;
return data;
});
document.getElementById("notificationDropdown") && document.getElementById("notificationDropdown")?.innerHTML === "" ? null : dropdownContents.innerHTML = "";
const notificationContainers = document.getElementsByClassName("notificationContainer");
while (notificationContainers[0]) {
notificationContainers[0].parentNode?.removeChild(notificationContainers[0]);
}
if (snapshotData.length > 0) {
snapshotData.forEach((notification) => {
const notificationContainer = document.createElement("div");
notificationContainer.classList.add("notificationContainer");
const readIndicator = document.createElement("div");
notification.read ? readIndicator.classList.add("readIndicator", "read") : readIndicator.classList.add("readIndicator", "unread");
notificationContainer.appendChild(readIndicator);
const textContainer = document.createElement("div");
const notificationTitle = document.createElement("h3");
notificationTitle.classList.add("notificationTitle");
notificationTitle.appendChild(document.createTextNode(notification.title));
const notificationBody = document.createElement("p");
notificationBody.classList.add("notificationBody");
notificationBody.appendChild(document.createTextNode(notification.body));
textContainer.appendChild(notificationTitle);
textContainer.appendChild(notificationBody);
notificationContainer.appendChild(textContainer);
readIndicator.addEventListener("click", () => {
event?.stopPropagation();
notification.read ? setDoc(notification.ref, { read: false }, { merge: true }) : setDoc(notification.ref, { read: true }, { merge: true });
});
textContainer.addEventListener("click", () => {
event?.stopPropagation();
setDoc(notification.ref, { read: true }, { merge: true });
window.location.href = '/' + notification.link;
});
dropdownContents.appendChild(notificationContainer);
});
} else {
const notificationContainer = document.createElement("div");
notificationContainer.innerHTML = "No notifications";
notificationContainer.style.textAlign = "center";
notificationContainer.style.padding = "1rem";
dropdownContents.appendChild(notificationContainer);
}
});
}
handleLoginContainer.appendChild(dropdownContainer);
}
});
}
|