diff --git a/components/alerts/create.vue b/components/alerts/create.vue
index 0f2ba0d..5028f7f 100644
--- a/components/alerts/create.vue
+++ b/components/alerts/create.vue
@@ -91,7 +91,7 @@
{{ actor.name }}
- ({{ [actor.ageFromBirth, actor.origin?.country?.alpha2].join(', ') }})
+ ({{ [actor.ageFromBirth, actor.origin?.country?.alpha2].filter(Boolean).join(', ') }})
diff --git a/components/header/header.vue b/components/header/header.vue
index 350cd12..fc57bad 100644
--- a/components/header/header.vue
+++ b/components/header/header.vue
@@ -78,69 +78,92 @@
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
pageContext.urlParsed.pathname.split('/')[1]);
const currentPath = `${pageContext.urlParsed.pathnameOriginal}${pageContext.urlParsed.searchOriginal || ''}`;
@@ -316,7 +342,7 @@ function blurSearch(event) {
height: 100%;
display: flex;
align-items: center;
- padding: 0 1rem 0 1.5rem;
+ padding: 0 1rem 0 0;
font-size: 0;
cursor: pointer;
@@ -332,6 +358,31 @@ function blurSearch(event) {
object-fit: cover;
}
+.notifs-bell {
+ padding: 0 1.25rem;
+ height: 100%;
+ fill: var(--shadow);
+
+ &:hover,
+ &.unread {
+ cursor: pointer;
+ fill: var(--primary);
+ }
+}
+
+.notifs {
+ overflow: auto;
+}
+
+.notif {
+ display: flex;
+ padding: .5rem 1rem;
+
+ &:not(:last-child) {
+ border-bottom: solid 1px var(--shadow-weak-30);
+ }
+}
+
.login {
display: flex;
align-items: center;
diff --git a/pages/users/@username/+onBeforeRender.js b/pages/users/@username/+onBeforeRender.js
index 6f90121..672ef63 100644
--- a/pages/users/@username/+onBeforeRender.js
+++ b/pages/users/@username/+onBeforeRender.js
@@ -11,7 +11,7 @@ export async function onBeforeRender(pageContext) {
: [],
]);
- console.log('out alerts', alerts);
+ console.log(pageContext.notifications);
if (!profile) {
throw render(404, `Cannot find user '${pageContext.routeParams.username}'.`);
diff --git a/renderer/+config.h.js b/renderer/+config.h.js
index 8ac21c6..6756388 100644
--- a/renderer/+config.h.js
+++ b/renderer/+config.h.js
@@ -6,5 +6,6 @@ export default {
'urlParsed',
'env',
'user',
+ 'notifications',
],
};
diff --git a/src/alerts.js b/src/alerts.js
index 55c0abc..3be77db 100755
--- a/src/alerts.js
+++ b/src/alerts.js
@@ -140,6 +140,28 @@ export async function removeAlert(alertId, reqUser) {
.delete();
}
+export async function fetchNotifications(reqUser, options = {}) {
+ const notifications = await knex('notifications')
+ .select('notifications.*', 'alerts.id as alert_id', 'scenes.title as scene_title')
+ .leftJoin('releases as scenes', 'scenes.id', 'notifications.scene_id')
+ .leftJoin('alerts', 'alerts.id', 'notifications.alert_id')
+ .where('notifications.user_id', reqUser.id)
+ .limit(options.limit || 10)
+ .orderBy('created_at', 'desc');
+
+ return notifications.map((notification) => ({
+ id: notification.id,
+ sceneId: notification.scene_id,
+ scene: {
+ id: notification.scene_id,
+ title: notification.scene_title,
+ },
+ alertId: notification.alert_id,
+ isSeen: notification.seen,
+ createdAt: notification.created_at,
+ }));
+}
+
export async function updateNotification(notificationId, updatedNotification, reqUser) {
await knex('notifications')
.where('id', notificationId)
diff --git a/src/web/alerts.js b/src/web/alerts.js
index 70faf2a..9b8773f 100755
--- a/src/web/alerts.js
+++ b/src/web/alerts.js
@@ -2,6 +2,7 @@ import {
fetchAlerts,
createAlert,
removeAlert,
+ fetchNotifications,
updateNotifications,
updateNotification,
} from '../alerts.js';
@@ -24,6 +25,14 @@ export async function removeAlertApi(req, res) {
res.status(204).send();
}
+export async function fetchNotificationsApi(req, res) {
+ const notifications = await fetchNotifications(req.user, {
+ limit: req.query.limit || 10,
+ });
+
+ res.send(notifications);
+}
+
export async function updateNotificationsApi(req, res) {
await updateNotifications(req.body, req.user);
diff --git a/src/web/server.js b/src/web/server.js
index 8f4d39e..0d3c125 100644
--- a/src/web/server.js
+++ b/src/web/server.js
@@ -51,6 +51,8 @@ import {
updateNotificationsApi,
} from './alerts.js';
+import { fetchNotifications } from '../alerts.js';
+
import initLogger from '../logger.js';
const logger = initLogger();
@@ -164,6 +166,8 @@ export default async function initServer() {
router.get('/api/tags', fetchTagsApi);
router.get('*', async (req, res, next) => {
+ const notifications = await fetchNotifications(req.user, { limit: 20 });
+
const pageContextInit = {
urlOriginal: req.originalUrl,
urlQuery: req.query, // vike's own query does not apply boolean parser
@@ -185,6 +189,7 @@ export default async function initServer() {
maxAggregateSize: config.database.manticore.maxAggregateSize,
media: config.media,
},
+ notifications,
};
const pageContext = await renderPage(pageContextInit);