mirror of
https://github.com/simple-login/app.git
synced 2024-09-20 15:05:59 +08:00
display notifications. user can mark a notification as read.
This commit is contained in:
parent
95c5cb8452
commit
b01c91423f
|
@ -710,7 +710,6 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<script src="{{ url_for('static', filename='node_modules/vue/dist/vue.min.js') }}"></script>
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#filter-app',
|
||||
|
|
|
@ -46,3 +46,73 @@
|
|||
introJs().start();
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="{{ url_for('static', filename='node_modules/vue/dist/vue.min.js') }}"></script>
|
||||
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#notification-app',
|
||||
delimiters: ["[[", "]]"], // necessary to avoid conflict with jinja
|
||||
data: {
|
||||
notifications: [],
|
||||
page: 0,
|
||||
loading: true,
|
||||
canLoadMore: true
|
||||
},
|
||||
computed: {
|
||||
has_non_read_notification: function () {
|
||||
for (let i = 0; i < this.notifications.length; i++) {
|
||||
if (!this.notifications[i].read) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
markAsRead: async function (notification) {
|
||||
notification.read = true;
|
||||
let res = await fetch(`/api/notifications/${notification.id}/read`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
|
||||
}
|
||||
},
|
||||
|
||||
loadMore: async function () {
|
||||
let that = this;
|
||||
that.page += 1;
|
||||
|
||||
let res = await fetch(`/api/notifications?page=${that.page}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
});
|
||||
if (res.ok) {
|
||||
let json = await res.json();
|
||||
if (json.length == 0) that.canLoadMore = false;
|
||||
that.notifications = that.notifications.concat(json);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
async mounted() {
|
||||
let that = this;
|
||||
let res = await fetch(`/api/notifications?page=${that.page}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
});
|
||||
if (res.ok) {
|
||||
let json = await res.json();
|
||||
that.notifications = json;
|
||||
that.loading = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -15,6 +15,38 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="notification-app" class="dropdown d-none d-md-flex">
|
||||
<a class="nav-link icon" data-toggle="collapse" href="#notifications" style="height: 100%">
|
||||
<i class="fe fe-bell"></i>
|
||||
<span v-if="has_non_read_notification" class="nav-unread"></span>
|
||||
<span v-else class="nav-read"></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow collapse" id="notifications">
|
||||
<div v-if="loading">Loading ...</div>
|
||||
<div class="dropdown-item d-flex" v-for="notification in notifications">
|
||||
<div class="flex-grow-1">
|
||||
<div v-html="notification.message"
|
||||
style="width: 40em; word-wrap:break-word; white-space: normal"></div>
|
||||
<div class="small text-muted">
|
||||
[[notification.created_at]]
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!notification.read">
|
||||
<i class="fe fe-check"
|
||||
@click="markAsRead(notification)"
|
||||
data-toggle="tooltip" title="mark as read"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<button v-if="canLoadMore" @click="loadMore()" class="btn btn-link">Load more</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="dropdown">
|
||||
<a href="#" class="nav-link pr-0 leading-none" data-toggle="dropdown">
|
||||
{% if current_user.profile_picture_id %}
|
||||
|
|
Loading…
Reference in a new issue