mirror of https://github.com/pixelfed/pixelfed.git
310 lines
9.3 KiB
Vue
310 lines
9.3 KiB
Vue
|
<template>
|
||
|
<div class="group-notification-component col-12 col-md-9" style="height: 100vh - 51px !important;overflow:hidden">
|
||
|
<div class="row h-100 bg-white">
|
||
|
<div class="col-12 col-md-8 border-left">
|
||
|
<div class="px-5">
|
||
|
<div class="my-4">
|
||
|
<p class="h1 font-weight-bold mb-1">Group Notifications</p>
|
||
|
<!-- <p class="lead text-muted mb-0">Latest notifications from your groups</p> -->
|
||
|
</div>
|
||
|
<!-- <div class="p-4 mb-4">
|
||
|
<p class="font-weight-bold text-center text-muted">You don't have any notifications</p>
|
||
|
</div> -->
|
||
|
|
||
|
<div v-if="notifications.length > 0" v-for="(n, index) in notifications" class="nitem card card-body shadow-none mb-3 py-2 px-0 rounded-pill" style="background-color: #F3F4F6">
|
||
|
<div class="media align-items-center px-3">
|
||
|
<img class="mr-3 rounded-circle" style="border:1px solid #ccc" :src="n.account.avatar" alt="" width="32px" height="32px">
|
||
|
<div class="media-body">
|
||
|
<div v-if="n.type == 'group:like'">
|
||
|
<p class="my-0">
|
||
|
<a :href="getProfileUrl(n.account)" data-placement="bottom" data-toggle="tooltip" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> liked your <a v-bind:href="getPostUrl(n.status)">post</a> in <a :href="n.group.url">{{n.group.name}}</a>
|
||
|
</p>
|
||
|
</div>
|
||
|
|
||
|
<div v-else-if="n.type == 'group:comment'">
|
||
|
<p class="my-0">
|
||
|
<a :href="getProfileUrl(n.account)" class="font-weight-bold text-dark word-break" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> commented on your <a class="font-weight-bold" v-bind:href="n.status.url">post</a> in <a :href="n.group.url">{{n.group.name}}</a>
|
||
|
</p>
|
||
|
</div>
|
||
|
|
||
|
<div v-else-if="n.type == 'mention'">
|
||
|
<p class="my-0">
|
||
|
<a :href="getProfileUrl(n.account)" data-placement="bottom" data-toggle="tooltip" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> <a v-bind:href="mentionUrl(n.status)">mentioned</a> you.
|
||
|
</p>
|
||
|
</div>
|
||
|
|
||
|
<div v-else-if="n.type == 'group.join.approved'">
|
||
|
<p class="my-0">
|
||
|
Your application to join <a :href="n.group.url" class="font-weight-bold text-dark word-break" :title="n.group.name">{{truncate(n.group.name)}}</a> was approved!
|
||
|
</p>
|
||
|
</div>
|
||
|
|
||
|
<div v-else-if="n.type == 'group.join.rejected'">
|
||
|
<p class="my-0">
|
||
|
Your application to join <a :href="n.group.url" class="font-weight-bold text-dark word-break" :title="n.group.name">{{truncate(n.group.name)}}</a> was rejected. You can re-apply to join in 6 months.
|
||
|
</p>
|
||
|
</div>
|
||
|
|
||
|
<div v-else>
|
||
|
<p class="my-0">Cannot display notification</p>
|
||
|
</div>
|
||
|
|
||
|
<!-- <div class="align-items-center">
|
||
|
<span class="small text-muted" data-toggle="tooltip" data-placement="bottom" :title="n.created_at">{{timeAgo(n.created_at)}}</span>
|
||
|
</div> -->
|
||
|
</div>
|
||
|
<div>
|
||
|
<!-- <div v-if="n.status && n.status && n.status.media_attachments && n.status.media_attachments.length">
|
||
|
<a :href="getPostUrl(n.status)">
|
||
|
<img :src="n.status.media_attachments[0].preview_url" width="32px" height="32px">
|
||
|
</a>
|
||
|
</div>
|
||
|
<div v-else-if="n.status && n.status.parent && n.status.parent.media_attachments && n.status.parent.media_attachments.length">
|
||
|
<a :href="n.status.parent.url">
|
||
|
<img :src="n.status.parent.media_attachments[0].preview_url" width="32px" height="32px">
|
||
|
</a>
|
||
|
</div>
|
||
|
|
||
|
<div v-else>
|
||
|
<a v-if="viewContext(n) != '/'" class="btn btn-outline-primary py-0 font-weight-bold" :href="viewContext(n)">View</a>
|
||
|
</div> -->
|
||
|
|
||
|
<div class="align-items-center text-muted">
|
||
|
<span class="small" data-toggle="tooltip" data-placement="bottom" :title="n.created_at">{{timeAgo(n.created_at)}}</span>
|
||
|
<span>·</span>
|
||
|
<div class="dropdown d-inline">
|
||
|
<a class="dropdown-toggle text-lighter" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||
|
<i class="far fa-cog fa-sm"></i>
|
||
|
</a>
|
||
|
|
||
|
<div class="dropdown-menu dropdown-menu-right">
|
||
|
<a class="dropdown-item font-weight-bold" href="#">Dismiss</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item font-weight-bold" href="#">Help</a>
|
||
|
<!-- <a class="dropdown-item font-weight-bold" href="#">Ignore</a> -->
|
||
|
<a class="dropdown-item font-weight-bold" href="#">Report</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="col-12 col-md-4 border-left bg-light">
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script type="text/javascript">
|
||
|
export default {
|
||
|
data() {
|
||
|
return {
|
||
|
notifications: [],
|
||
|
initialLoad: false,
|
||
|
loading: true,
|
||
|
page: 1
|
||
|
}
|
||
|
},
|
||
|
|
||
|
mounted() {
|
||
|
this.fetchNotifications();
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
fetchNotifications() {
|
||
|
axios.get('/api/pixelfed/v1/accounts/verify_credentials').then(res => {
|
||
|
window._sharedData.curUser = res.data;
|
||
|
window.App.util.navatar();
|
||
|
});
|
||
|
axios.get('/api/v0/groups/self/notifications')
|
||
|
.then(res => {
|
||
|
let data = res.data.filter(n => {
|
||
|
if(n.type == 'share' && !n.status) {
|
||
|
return false;
|
||
|
}
|
||
|
if(n.type == 'comment' && !n.status) {
|
||
|
return false;
|
||
|
}
|
||
|
if(n.type == 'mention' && !n.status) {
|
||
|
return false;
|
||
|
}
|
||
|
if(n.type == 'favourite' && !n.status) {
|
||
|
return false;
|
||
|
}
|
||
|
if(n.type == 'follow' && !n.account) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
// let ids = res.data.map(n => n.id);
|
||
|
// this.notificationMaxId = Math.max(...ids);
|
||
|
this.notifications = data;
|
||
|
// $('.notification-card .loader').addClass('d-none');
|
||
|
// $('.notification-card .contents').removeClass('d-none');
|
||
|
});
|
||
|
},
|
||
|
|
||
|
// infiniteNotifications($state) {
|
||
|
// if(this.notificationCursor > 10) {
|
||
|
// $state.complete();
|
||
|
// return;
|
||
|
// }
|
||
|
// axios.get('/api/pixelfed/v1/notifications', {
|
||
|
// params: {
|
||
|
// max_id: this.notificationMaxId
|
||
|
// }
|
||
|
// }).then(res => {
|
||
|
// if(res.data.length) {
|
||
|
// let data = res.data.filter(n => {
|
||
|
// if(n.type == 'share' && !n.status) {
|
||
|
// return false;
|
||
|
// }
|
||
|
// if(n.type == 'comment' && !n.status) {
|
||
|
// return false;
|
||
|
// }
|
||
|
// if(n.type == 'mention' && !n.status) {
|
||
|
// return false;
|
||
|
// }
|
||
|
// if(n.type == 'favourite' && !n.status) {
|
||
|
// return false;
|
||
|
// }
|
||
|
// if(n.type == 'follow' && !n.account) {
|
||
|
// return false;
|
||
|
// }
|
||
|
// if(_.find(this.notifications, {id: n.id})) {
|
||
|
// return false;
|
||
|
// }
|
||
|
// return true;
|
||
|
// });
|
||
|
// this.notifications.push(...data);
|
||
|
// this.notificationCursor++;
|
||
|
// $state.loaded();
|
||
|
// } else {
|
||
|
// $state.complete();
|
||
|
// }
|
||
|
// });
|
||
|
// },
|
||
|
|
||
|
truncate(text) {
|
||
|
if(text.length <= 15) {
|
||
|
return text;
|
||
|
}
|
||
|
|
||
|
return text.slice(0,15) + '...'
|
||
|
},
|
||
|
|
||
|
timeAgo(ts) {
|
||
|
let date = Date.parse(ts);
|
||
|
let seconds = Math.floor((new Date() - date) / 1000);
|
||
|
let interval = Math.floor(seconds / 31536000);
|
||
|
if (interval >= 1) {
|
||
|
return interval + "y";
|
||
|
}
|
||
|
interval = Math.floor(seconds / 604800);
|
||
|
if (interval >= 1) {
|
||
|
return interval + "w";
|
||
|
}
|
||
|
interval = Math.floor(seconds / 86400);
|
||
|
if (interval >= 1) {
|
||
|
return interval + "d";
|
||
|
}
|
||
|
interval = Math.floor(seconds / 3600);
|
||
|
if (interval >= 1) {
|
||
|
return interval + "h";
|
||
|
}
|
||
|
interval = Math.floor(seconds / 60);
|
||
|
if (interval >= 1) {
|
||
|
return interval + "m";
|
||
|
}
|
||
|
return Math.floor(seconds) + "s";
|
||
|
},
|
||
|
|
||
|
mentionUrl(status) {
|
||
|
let username = status.account.username;
|
||
|
let id = status.id;
|
||
|
return '/p/' + username + '/' + id;
|
||
|
},
|
||
|
|
||
|
followProfile(n) {
|
||
|
let self = this;
|
||
|
let id = n.account.id;
|
||
|
axios.post('/i/follow', {
|
||
|
item: id
|
||
|
}).then(res => {
|
||
|
self.notifications.map(notification => {
|
||
|
if(notification.account.id === id) {
|
||
|
notification.relationship.following = true;
|
||
|
}
|
||
|
});
|
||
|
}).catch(err => {
|
||
|
if(err.response.data.message) {
|
||
|
swal('Error', err.response.data.message, 'error');
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
viewContext(n) {
|
||
|
switch(n.type) {
|
||
|
case 'follow':
|
||
|
return n.account.url;
|
||
|
break;
|
||
|
case 'mention':
|
||
|
return n.status.url;
|
||
|
break;
|
||
|
case 'like':
|
||
|
case 'favourite':
|
||
|
case 'comment':
|
||
|
return n.status.url;
|
||
|
break;
|
||
|
case 'tagged':
|
||
|
return n.tagged.post_url;
|
||
|
break;
|
||
|
case 'direct':
|
||
|
return '/account/direct/t/'+n.account.id;
|
||
|
break
|
||
|
}
|
||
|
return '/';
|
||
|
},
|
||
|
|
||
|
getProfileUrl(account) {
|
||
|
if(account.local == true) {
|
||
|
return account.url;
|
||
|
}
|
||
|
|
||
|
return '/i/web/profile/_/' + account.id;
|
||
|
},
|
||
|
|
||
|
getPostUrl(status) {
|
||
|
if(status.local == true) {
|
||
|
return status.url;
|
||
|
}
|
||
|
|
||
|
return '/i/web/post/_/' + status.account.id + '/' + status.id;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss">
|
||
|
.group-notification-component {
|
||
|
.dropdown-toggle::after {
|
||
|
content: '';
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
.nitem {
|
||
|
a {
|
||
|
color: #000;
|
||
|
font-weight: 700 !important;
|
||
|
|
||
|
&:hover,
|
||
|
&:focus {
|
||
|
color: #121416 !important;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|