mirror of
https://github.com/axllent/mailpit.git
synced 2025-01-26 03:52:09 +02:00
Merge branch 'release/v1.6.3'
This commit is contained in:
commit
9ae9104ca3
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
Notable changes to Mailpit will be documented in this file.
|
Notable changes to Mailpit will be documented in this file.
|
||||||
|
|
||||||
|
## [v1.6.3]
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
- Display clickable toast notifications for new messages
|
||||||
|
|
||||||
|
|
||||||
## [v1.6.2]
|
## [v1.6.2]
|
||||||
|
|
||||||
### Bugfix
|
### Bugfix
|
||||||
|
@ -3,6 +3,7 @@ import commonMixins from './mixins.js';
|
|||||||
import Message from './templates/Message.vue';
|
import Message from './templates/Message.vue';
|
||||||
import MessageSummary from './templates/MessageSummary.vue';
|
import MessageSummary from './templates/MessageSummary.vue';
|
||||||
import MessageRelease from './templates/MessageRelease.vue';
|
import MessageRelease from './templates/MessageRelease.vue';
|
||||||
|
import MessageToast from './templates/MessageToast.vue';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Tinycon from 'tinycon';
|
import Tinycon from 'tinycon';
|
||||||
|
|
||||||
@ -12,7 +13,8 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
Message,
|
Message,
|
||||||
MessageSummary,
|
MessageSummary,
|
||||||
MessageRelease
|
MessageRelease,
|
||||||
|
MessageToast
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
@ -41,6 +43,7 @@ export default {
|
|||||||
lastLoaded: false,
|
lastLoaded: false,
|
||||||
relayConfig: {},
|
relayConfig: {},
|
||||||
releaseAddresses: false,
|
releaseAddresses: false,
|
||||||
|
toastMessage: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -205,6 +208,7 @@ export default {
|
|||||||
let self = this;
|
let self = this;
|
||||||
self.selected = [];
|
self.selected = [];
|
||||||
self.releaseAddresses = false;
|
self.releaseAddresses = false;
|
||||||
|
self.toastMessage = false;
|
||||||
self.existingTags = JSON.parse(JSON.stringify(self.tags));
|
self.existingTags = JSON.parse(JSON.stringify(self.tags));
|
||||||
|
|
||||||
let uri = 'api/v1/message/' + self.currentPath
|
let uri = 'api/v1/message/' + self.currentPath
|
||||||
@ -396,10 +400,16 @@ export default {
|
|||||||
if (response.Type == "new" && response.Data) {
|
if (response.Type == "new" && response.Data) {
|
||||||
if (!self.searching) {
|
if (!self.searching) {
|
||||||
if (self.start < 1) {
|
if (self.start < 1) {
|
||||||
|
// first page
|
||||||
self.items.unshift(response.Data);
|
self.items.unshift(response.Data);
|
||||||
if (self.items.length > self.limit) {
|
if (self.items.length > self.limit) {
|
||||||
self.items.pop();
|
self.items.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// first message was open, set messagePrev
|
||||||
|
if (!self.messagePrev) {
|
||||||
|
self.messagePrev = response.Data.ID;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.start++;
|
self.start++;
|
||||||
}
|
}
|
||||||
@ -416,6 +426,7 @@ export default {
|
|||||||
|
|
||||||
let from = response.Data.From != null ? response.Data.From.Address : '[unknown]';
|
let from = response.Data.From != null ? response.Data.From.Address : '[unknown]';
|
||||||
self.browserNotify("New mail from: " + from, response.Data.Subject);
|
self.browserNotify("New mail from: " + from, response.Data.Subject);
|
||||||
|
self.setMessageToast(response.Data);
|
||||||
} else if (response.Type == "prune") {
|
} else if (response.Type == "prune") {
|
||||||
// messages have been deleted, reload messages to adjust
|
// messages have been deleted, reload messages to adjust
|
||||||
self.scrollInPlace = true;
|
self.scrollInPlace = true;
|
||||||
@ -591,6 +602,18 @@ export default {
|
|||||||
document.querySelector('#ReleaseModal input[role="combobox"]').focus()
|
document.querySelector('#ReleaseModal input[role="combobox"]').focus()
|
||||||
}, 500);
|
}, 500);
|
||||||
}, 300);
|
}, 300);
|
||||||
|
},
|
||||||
|
|
||||||
|
setMessageToast: function (m) {
|
||||||
|
if (this.toastMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toastMessage = m;
|
||||||
|
},
|
||||||
|
|
||||||
|
clearMessageToast: function () {
|
||||||
|
this.toastMessage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1014,4 +1037,6 @@ export default {
|
|||||||
<MessageRelease v-if="releaseAddresses" :message="message" :relayConfig="relayConfig"
|
<MessageRelease v-if="releaseAddresses" :message="message" :relayConfig="relayConfig"
|
||||||
:releaseAddresses="releaseAddresses"></MessageRelease>
|
:releaseAddresses="releaseAddresses"></MessageRelease>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<MessageToast v-if="toastMessage" :message="toastMessage" @clearMessageToast="clearMessageToast"></MessageToast>
|
||||||
</template>
|
</template>
|
||||||
|
2
server/ui-src/assets/bootstrap.scss
vendored
2
server/ui-src/assets/bootstrap.scss
vendored
@ -32,7 +32,7 @@
|
|||||||
// @import "../../../node_modules/bootstrap/scss/progress";
|
// @import "../../../node_modules/bootstrap/scss/progress";
|
||||||
@import "../../../node_modules/bootstrap/scss/list-group";
|
@import "../../../node_modules/bootstrap/scss/list-group";
|
||||||
@import "../../../node_modules/bootstrap/scss/close";
|
@import "../../../node_modules/bootstrap/scss/close";
|
||||||
// @import "../../../node_modules/bootstrap/scss/toasts";
|
@import "../../../node_modules/bootstrap/scss/toasts";
|
||||||
@import "../../../node_modules/bootstrap/scss/modal";
|
@import "../../../node_modules/bootstrap/scss/modal";
|
||||||
// @import "../../../node_modules/bootstrap/scss/tooltip";
|
// @import "../../../node_modules/bootstrap/scss/tooltip";
|
||||||
// @import "../../../node_modules/bootstrap/scss/popover";
|
// @import "../../../node_modules/bootstrap/scss/popover";
|
||||||
|
44
server/ui-src/templates/MessageToast.vue
Normal file
44
server/ui-src/templates/MessageToast.vue
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<script>
|
||||||
|
import { Toast } from 'bootstrap';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
message: Object
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
let self = this;
|
||||||
|
let el = document.getElementById('messageToast');
|
||||||
|
if (el) {
|
||||||
|
el.addEventListener('hidden.bs.toast', () => {
|
||||||
|
self.$emit("clearMessageToast");
|
||||||
|
})
|
||||||
|
|
||||||
|
let b = Toast.getOrCreateInstance(el);
|
||||||
|
b.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||||
|
<div id="messageToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||||
|
<div class="toast-header">
|
||||||
|
<i class="bi bi-envelope-exclamation-fill me-2"></i>
|
||||||
|
<strong class="me-auto"><a :href="'#' + message.ID">New message</a></strong>
|
||||||
|
<small class="text-body-secondary">now</small>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="toast-body">
|
||||||
|
<div>
|
||||||
|
<a :href="'#' + message.ID" class="d-block text-truncate text-muted">
|
||||||
|
<template v-if="message.Subject != ''">{{ message.Subject }}</template>
|
||||||
|
<template v-else>[ no subject ]</template>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
x
Reference in New Issue
Block a user