Added notification bell, WIP.
This commit is contained in:
parent
dc5affb4cf
commit
342ba6191e
|
@ -91,7 +91,7 @@
|
|||
|
||||
<div class="result-label">
|
||||
{{ actor.name }}
|
||||
<template v-if="actor.ageFromBirth || actor.origin?.country">({{ [actor.ageFromBirth, actor.origin?.country?.alpha2].join(', ') }})</template>
|
||||
<template v-if="actor.ageFromBirth || actor.origin?.country">({{ [actor.ageFromBirth, actor.origin?.country?.alpha2].filter(Boolean).join(', ') }})</template>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -78,20 +78,42 @@
|
|||
</button>
|
||||
</form>
|
||||
|
||||
<VDropdown
|
||||
<div
|
||||
v-if="user"
|
||||
class="userpanel"
|
||||
:class="{ searching: searchFocused }"
|
||||
>
|
||||
<VDropdown
|
||||
:triggers="['click']"
|
||||
:prevent-overflow="true"
|
||||
>
|
||||
<div
|
||||
class="userpanel"
|
||||
:class="{ searching: searchFocused }"
|
||||
<Icon
|
||||
icon="bell2"
|
||||
class="notifs-bell"
|
||||
:class="{ unread: notifications.some((notif) => !notif.isSeen) }"
|
||||
/>
|
||||
|
||||
<template #popper>
|
||||
<div class="menu">
|
||||
<ul class="notifs nolist">
|
||||
<li
|
||||
v-for="notif in notifications"
|
||||
:key="notif.id"
|
||||
class="notif"
|
||||
>{{ notif.scene.title }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</VDropdown>
|
||||
|
||||
<VDropdown
|
||||
:triggers="['click']"
|
||||
:prevent-overflow="true"
|
||||
>
|
||||
<img
|
||||
:src="user.avatar"
|
||||
class="avatar"
|
||||
>
|
||||
</div>
|
||||
|
||||
<template #popper>
|
||||
<div class="menu">
|
||||
|
@ -141,6 +163,7 @@
|
|||
</div>
|
||||
</template>
|
||||
</VDropdown>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="allowLogin"
|
||||
|
@ -181,11 +204,14 @@ import logo from '../../assets/img/logo.svg?raw'; // eslint-disable-line import/
|
|||
const pageContext = inject('pageContext');
|
||||
|
||||
const user = pageContext.user;
|
||||
const notifications = pageContext.notifications;
|
||||
const query = ref(pageContext.urlParsed.search.q || '');
|
||||
const allowLogin = pageContext.env.allowLogin;
|
||||
const searchFocused = ref(false);
|
||||
const showSettings = ref(false);
|
||||
|
||||
console.log(notifications);
|
||||
|
||||
const activePage = computed(() => 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;
|
||||
|
|
|
@ -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}'.`);
|
||||
|
|
|
@ -6,5 +6,6 @@ export default {
|
|||
'urlParsed',
|
||||
'env',
|
||||
'user',
|
||||
'notifications',
|
||||
],
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue