1
0
mirror of https://github.com/axllent/mailpit.git synced 2024-12-30 23:17:59 +02:00

Feature: Mark all messages as read

This commit is contained in:
Ralph Slooten 2022-08-07 09:34:06 +12:00
parent f260495495
commit d4cf95363f
4 changed files with 95 additions and 8 deletions

View File

@ -218,6 +218,22 @@ func apiUnreadOne(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("ok"))
}
// Mark single message as unread
func apiMarkAllRead(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
mailbox := vars["mailbox"]
err := storage.MarkAllRead(mailbox)
if err != nil {
httpError(w, err.Error())
return
}
w.Header().Add("Content-Type", "text/plain")
_, _ = w.Write([]byte("ok"))
}
// Websocket to broadcast changes
func apiWebsocket(w http.ResponseWriter, r *http.Request) {
websockets.ServeWs(websockets.MessageHub, w, r)

View File

@ -39,6 +39,7 @@ func Listen() {
r.HandleFunc("/api/{mailbox}/search", middleWareFunc(apiSearchMailbox))
r.HandleFunc("/api/{mailbox}/delete", middleWareFunc(apiDeleteAll))
r.HandleFunc("/api/{mailbox}/events", apiWebsocket)
r.HandleFunc("/api/{mailbox}/read", apiMarkAllRead)
r.HandleFunc("/api/{mailbox}/{id}/source", middleWareFunc(apiDownloadSource))
r.HandleFunc("/api/{mailbox}/{id}/part/{partID}", middleWareFunc(apiDownloadAttachment))
r.HandleFunc("/api/{mailbox}/{id}/delete", middleWareFunc(apiDeleteOne))

View File

@ -198,6 +198,16 @@ export default {
});
},
markAllRead: function() {
let self = this;
let uri = 'api/' + self.mailbox + '/read'
self.get(uri, false, function(response) {
window.location.hash = "";
self.scrollInPlace = true;
self.loadMessages();
});
},
// websocket connect
connect: function () {
let wsproto = location.protocol == 'https:' ? 'wss' : 'ws';
@ -360,15 +370,15 @@ export default {
<div class="row flex-fill" style="min-height:0">
<div class="d-none d-md-block col-lg-2 col-md-3 mh-100 position-relative" style="overflow-y: auto;">
<ul class="list-unstyled mt-3 mb-5">
<li v-if="isConnected" title="Messages will auto-load">
<li v-if="isConnected" title="Messages will auto-load" class="mb-2">
<i class="bi bi-power text-success"></i>
Connected
</li>
<li v-else title="You need to manually refresh your mailbox">
<li v-else title="You need to manually refresh your mailbox" class="mb-3">
<i class="bi bi-power text-danger"></i>
Disconnected
</li>
<li class="mt-3">
<li class="mb-5">
<a class="position-relative ps-0" href="#" v-on:click="reloadMessages">
<i class="bi bi-envelope me-1" v-if="isConnected"></i>
<i class="bi bi-arrow-clockwise me-1" v-else></i>
@ -378,20 +388,26 @@ export default {
</span>
</a>
</li>
<li class="mt-3">
<a v-if="total" href="#" data-bs-toggle="modal" data-bs-target="#DeleteAllModal">
<li class="my-3" v-if="unread">
<a href="#" data-bs-toggle="modal" data-bs-target="#MarkAllReadModal">
<i class="bi bi-check2-square"></i>
Mark all read
</a>
</li>
<li class="my-3" v-if="total">
<a href="#" data-bs-toggle="modal" data-bs-target="#DeleteAllModal">
<i class="bi bi-trash-fill me-1 text-danger"></i>
Delete all
</a>
</li>
<li class="mt-3" v-if="notificationsSupported && !notificationsEnabled">
<li class="my-3" v-if="notificationsSupported && !notificationsEnabled">
<a href="#" data-bs-toggle="modal" data-bs-target="#EnableNotificationsModal" title="Enable browser notifications">
<i class="bi bi-bell"></i>
Enable alerts
</a>
</li>
<li class="mt-5 position-fixed bottom-0">
<a href="https://github.com/axllent/mailpit" target="_blank" class="text-muted w-100 d-block bg-white py-2">
<a href="https://github.com/axllent/mailpit" target="_blank" class="text-muted w-100 d-block bg-white my-3">
<i class="bi bi-github"></i>
GitHub
</a>
@ -435,7 +451,7 @@ export default {
</div>
</a>
</div>
<div v-else class="text-muted py-3">No messages</div>
<div v-else class="text-muted my-3">No messages</div>
</div>
<Message v-if="message" :message="message" :mailbox="mailbox"></Message>
@ -468,6 +484,25 @@ export default {
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="MarkAllReadModal" tabindex="-1" aria-labelledby="MarkAllReadModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="MarkAllReadModalLabel">Mark all messages as read?</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
This will mark {{ formatNumber(unread) }} message<span v-if="unread > 1">s</span> as read.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" v-on:click="markAllRead">Confirm</button>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="EnableNotificationsModal" tabindex="-1" aria-labelledby="EnableNotificationsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">

View File

@ -574,3 +574,38 @@ func DeleteAllMessages(mailbox string) error {
return nil
}
// MarkAllRead will mark every unread message in a mailbox as read
func MarkAllRead(mailbox string) error {
mailbox = sanitizeMailboxName(mailbox)
totalStart := time.Now()
q, err := db.FindAll(clover.NewQuery(mailbox).
Where(clover.Field("Read").IsFalse()))
if err != nil {
return err
}
total := len(q)
updates := make(map[string]interface{})
updates["Read"] = true
for _, m := range q {
if err := db.UpdateById(mailbox, m.ObjectId(), updates); err != nil {
logger.Log().Error(err)
return err
}
}
if err := statsRefresh(mailbox); err != nil {
return err
}
elapsed := time.Since(totalStart)
logger.Log().Debugf("[db] marked %d messages in %s as read in %s", total, mailbox, elapsed)
return nil
}