traxxx/assets/components/header/notifications.vue

342 lines
6.9 KiB
Vue
Raw Normal View History

2021-04-22 17:44:23 +00:00
<template>
2021-04-28 23:45:01 +00:00
<div class="notifications">
2021-04-22 17:44:23 +00:00
<div class="notifications-header">
<h4 class="notifications-title">Notifications</h4>
<div class="notifications-actions">
<Icon
2021-05-08 22:23:10 +00:00
v-if="unseenCount > 0"
v-tooltip="'Mark all as seen'"
2021-04-22 17:44:23 +00:00
icon="checkmark"
@click="checkNotifications"
2021-04-22 17:44:23 +00:00
/>
<Icon
2021-05-08 22:23:10 +00:00
v-tooltip="'Add alert'"
2021-04-22 17:44:23 +00:00
icon="plus3"
@click="$emit('addAlert')"
2021-04-22 17:44:23 +00:00
/>
</div>
</div>
<div class="notifications-body">
<div
2021-04-22 17:44:23 +00:00
v-if="notifications.length === 0"
class="notifications-empty"
>No notifications</div>
2021-04-22 17:44:23 +00:00
<ul
v-else
class="nolist"
>
<li
v-for="notification in notifications"
:key="`notification-${notification.id}`"
:class="{ unseen: !notification.seen }"
2021-04-22 17:44:23 +00:00
class="notification"
2021-04-28 23:45:01 +00:00
@click="checkNotification(notification.id, true)"
2021-04-22 17:44:23 +00:00
>
<router-link
:to="`/scene/${notification.scene.id}/${notification.scene.slug}`"
class="notification-link"
>
<img
:src="getPath(notification.scene.poster, 'thumbnail')"
class="poster"
>
<div class="notification-body">
<div class="notification-row notification-title">
<img
v-if="notification.scene.entity.type === 'network' || notification.scene.entity.independent"
2021-04-27 02:41:22 +00:00
v-tooltip="notification.scene.entity.name"
:src="`/img/logos/${notification.scene.entity.slug}/favicon_${theme === 'dark' ? 'light' : 'dark'}.png`"
class="notification-favicon"
>
<img
v-else
2021-04-27 02:41:22 +00:00
v-tooltip="notification.scene.entity.name"
:src="`/img/logos/${notification.scene.entity.parent.slug}/favicon_${theme === 'dark' ? 'light' : 'dark'}.png`"
class="notification-favicon"
>
New&nbsp;<ul
v-if="notification.alert?.tags.length > 0"
class="nolist notification-tags"
>
<li
v-for="tag in notification.alert.tags"
:key="`notification-tag-${tag.slug}`"
class="notification-tag"
>{{ tag.name }}</li>&nbsp;
</ul>scene
</div>
2021-04-27 02:41:22 +00:00
<div class="notification-row notification-details">
<span class="notification-date">{{ formatDate(notification.scene.date, 'MMM D') }}</span>
<ul
v-if="notification.scene.actors.length > 0"
class="nolist notification-actors"
>
<li
v-for="actor in notification.scene.actors"
:key="`notification-actor-${actor.slug}`"
class="notification-actor"
>{{ actor.name }}</li>
</ul>
</div>
2021-04-22 17:44:23 +00:00
</div>
<Icon
v-if="!notification.seen"
v-tooltip="'Mark as seen'"
icon="checkmark"
class="notification-check"
2021-04-28 23:45:01 +00:00
@click.prevent.stop="checkNotification(notification.id)"
/>
2021-04-27 02:41:22 +00:00
<Icon
v-if="notification.alert"
2023-11-24 01:10:03 +00:00
v-tooltip="`You set an alert for scenes with <strong>${notification.alert.all ? 'all of' : 'any of'}</strong> <strong>${notification.alert.actors.map(actor => actor.name).join(', ') || 'any actor'}</strong> containing <strong>${notification.alert.tags.map(tag => tag.name).join(', ') || 'any tags'}</strong> from <strong>${notification.alert.entities.map((entity) => entity.name).join(', ') || 'any channel'}</strong> matching <strong>${notification.alert.matches.map((match) => `${match.property}: ${match.expression}`).join(', ') || 'any text'}</strong>`"
2021-04-27 02:41:22 +00:00
icon="question5"
2021-04-28 23:45:01 +00:00
@click.prevent.stop
2021-04-27 02:41:22 +00:00
/>
2021-04-22 17:44:23 +00:00
</router-link>
</li>
</ul>
</div>
2021-05-08 22:23:10 +00:00
<div @click="events.emit('blur')">
2021-05-08 22:23:10 +00:00
<router-link
to="/notifications"
class="notification-link notification-more"
>See all</router-link>
</div>
2021-04-22 17:44:23 +00:00
</div>
</template>
<script>
async function checkNotifications() {
await this.$store.dispatch('checkNotifications');
2021-05-08 22:23:10 +00:00
this.$emit('check');
}
2021-04-22 17:44:23 +00:00
2021-04-28 23:45:01 +00:00
async function checkNotification(notificationId, blur) {
await this.$store.dispatch('checkNotification', notificationId);
2021-05-08 22:23:10 +00:00
this.$emit('check');
2021-04-28 23:45:01 +00:00
if (blur) {
this.events.emit('blur');
}
2021-04-22 17:44:23 +00:00
}
export default {
2021-05-08 22:23:10 +00:00
props: {
notifications: {
type: Array,
default: () => [],
},
unseenCount: {
type: Number,
default: 0,
},
},
emits: ['addAlert'],
2021-04-22 17:44:23 +00:00
data() {
return {
showAddAlert: false,
};
},
methods: {
checkNotifications,
checkNotification,
2021-04-22 17:44:23 +00:00
},
};
</script>
<style lang="scss" scoped>
.notifications {
width: 30rem;
2021-05-08 22:23:10 +00:00
max-height: calc(100vh - 5rem);
display: flex;
flex-direction: column;
2021-04-22 17:44:23 +00:00
}
.notifications-header {
display: flex;
justify-content: space-between;
.icon {
padding: .5rem;
fill: var(--shadow);
2021-05-08 22:23:10 +00:00
&:first-child {
padding: .5rem .5rem .5rem 1.5rem;
}
2021-04-27 02:41:22 +00:00
&:last-child {
2021-05-08 22:23:10 +00:00
padding: .5rem 1.5rem .5rem .5rem;
2021-04-27 02:41:22 +00:00
}
2021-05-08 22:23:10 +00:00
&:hover {
2021-04-22 17:44:23 +00:00
fill: var(--primary);
cursor: pointer;
}
}
}
.notifications-title {
display: inline-block;
padding: .5rem 1rem;
margin: 0;
color: var(--shadow);
font-size: 1rem;
font-weight: bold;
}
.notifications-body {
2021-05-08 22:23:10 +00:00
flex-grow: 1;
overflow-y: auto;
2021-04-22 17:44:23 +00:00
box-shadow: 0 0 3px var(--shadow-weak);
}
.notifications-empty {
padding: .5rem 1rem;
color: var(--shadow);
}
2021-04-22 17:44:23 +00:00
.notification {
display: block;
2021-04-27 02:41:22 +00:00
border-right: solid .5rem var(--shadow-touch);
color: var(--text);
&.unseen {
border-right: solid .5rem var(--primary);
}
2021-04-22 17:44:23 +00:00
2021-04-27 01:56:38 +00:00
.icon {
2021-04-27 02:41:22 +00:00
padding: 1.3rem .5rem;
2021-04-27 01:56:38 +00:00
fill: var(--shadow-weak);
2021-05-08 22:23:10 +00:00
&.notification-check {
padding: 1.3rem .5rem 1.3rem 1rem;
}
2021-04-27 02:41:22 +00:00
&:last-child {
padding: 1.3rem 1rem 1.3rem .5rem;
}
2021-04-27 01:56:38 +00:00
&:hover {
fill: var(--primary);
}
}
2021-04-22 17:44:23 +00:00
&:not(:last-child) {
2021-04-27 02:41:22 +00:00
border-bottom: solid 1px var(--shadow-hint);
2021-05-08 22:23:10 +00:00
margin: 0 0 -1px 0;
2021-04-22 17:44:23 +00:00
}
&:hover {
2021-04-27 02:41:22 +00:00
background: var(--shadow-touch);
&:not(.unseen) {
border-right: solid .5rem var(--shadow-weak);
}
2021-04-22 17:44:23 +00:00
}
}
.notification-link {
display: flex;
align-items: stretch;
2021-04-22 17:44:23 +00:00
color: inherit;
text-decoration: none;
}
.notification-body {
flex-grow: 1;
2021-04-27 02:41:22 +00:00
padding: .4rem 0 0 0;
overflow: hidden;
}
.notification-row {
display: flex;
overflow: hidden;
2021-04-27 02:41:22 +00:00
}
2021-04-27 02:41:22 +00:00
.notification-title {
margin: .15rem .5rem .3rem .5rem;
2021-04-22 17:44:23 +00:00
}
.notification-favicon {
width: 1rem;
height: 1rem;
margin: 0 .5rem 0 0;
}
2021-04-27 02:41:22 +00:00
.notification-tags {
white-space: nowrap;
}
.notification-actors {
2021-04-27 02:41:22 +00:00
padding: 0 .5rem;
height: 1.25rem;
display: inline-block;
overflow: hidden;
}
2021-04-27 02:41:22 +00:00
.notification-date {
width: 3rem;
flex-shrink: 0;
padding: .25rem .25rem .35rem .25rem;
border-right: solid 1px var(--shadow-hint);
border-top: solid 1px var(--shadow-hint);
color: var(--shadow-strong);
font-size: .8rem;
text-align: center;
}
.notification-actor,
.notification-tag {
white-space: nowrap;
&:not(:last-child)::after {
content: ',';
padding: 0 .1rem 0 0;
}
}
.notification-actor {
2021-04-27 02:41:22 +00:00
padding: .25rem .15rem .35rem 0;
color: var(--shadow-strong);
font-size: .9rem;
}
.notification-tag {
font-weight: bold;
}
2021-05-08 22:23:10 +00:00
.notification-more {
display: block;
padding: .5rem 1rem;
color: var(--shadow);
text-align: center;
font-size: .9rem;
font-weight: bold;
&:hover {
color: var(--primary);
}
}
2021-04-22 17:44:23 +00:00
.poster {
2021-04-27 02:41:22 +00:00
width: 6rem;
2021-04-28 23:45:01 +00:00
height: 3.6rem;
2021-04-22 17:44:23 +00:00
object-fit: cover;
object-position: center;
}
</style>