1
0
mirror of https://github.com/axllent/mailpit.git synced 2025-12-20 00:12:26 +02:00
Files
mailpit/server/ui-src/views/SearchView.vue

201 lines
5.1 KiB
Vue

<script>
import About from "../components/AppAbout.vue";
import AjaxLoader from "../components/AjaxLoader.vue";
import CommonMixins from "../mixins/CommonMixins";
import ListMessages from "../components/ListMessages.vue";
import MessagesMixins from "../mixins/MessagesMixins";
import NavSearch from "../components/NavSearch.vue";
import NavTags from "../components/NavTags.vue";
import Pagination from "../components/NavPagination.vue";
import SearchForm from "../components/SearchForm.vue";
import { mailbox } from "../stores/mailbox";
import { pagination } from "../stores/pagination";
export default {
components: {
About,
AjaxLoader,
ListMessages,
NavSearch,
NavTags,
Pagination,
SearchForm,
},
mixins: [CommonMixins, MessagesMixins],
// global event bus to handle message status changes
inject: ["eventBus"],
data() {
return {
mailbox,
pagination,
delayedRefresh: false,
};
},
watch: {
$route() {
this.doSearch();
},
},
mounted() {
mailbox.searching = this.getSearch();
this.doSearch();
// subscribe to events
this.eventBus.on("update", this.handleWSUpdate);
this.eventBus.on("delete", this.handleWSDelete);
this.eventBus.on("truncate", this.handleWSTruncate);
},
unmounted() {
// unsubscribe from events
this.eventBus.off("update", this.handleWSUpdate);
this.eventBus.off("delete", this.handleWSDelete);
this.eventBus.off("truncate", this.handleWSTruncate);
},
methods: {
doSearch() {
const s = this.getSearch();
if (!s) {
mailbox.searching = false;
this.$router.push("/");
return;
}
mailbox.searching = s;
this.apiURI = this.resolve(`/api/v1/search`) + "?query=" + encodeURIComponent(s);
if (mailbox.timeZone !== "" && (s.indexOf("after:") !== -1 || s.indexOf("before:") !== -1)) {
this.apiURI += "&tz=" + encodeURIComponent(mailbox.timeZone);
}
this.loadMessages();
},
// handler for websocket message updates
handleWSUpdate(data) {
for (let x = 0; x < this.mailbox.messages.length; x++) {
if (this.mailbox.messages[x].ID === data.ID) {
// update message
this.mailbox.messages[x] = { ...this.mailbox.messages[x], ...data };
return;
}
}
},
// handler for websocket message deletion
handleWSDelete(data) {
let removed = 0;
for (let x = 0; x < this.mailbox.messages.length; x++) {
if (this.mailbox.messages[x].ID === data.ID) {
// remove message from the list
this.mailbox.messages.splice(x, 1);
removed++;
continue;
}
}
if (!removed || this.delayedRefresh) {
// nothing changed on this screen, or a refresh is queued, don't refresh
return;
}
// delayedRefresh prevents unnecessary reloads when multiple messages are deleted
this.delayedRefresh = true;
window.setTimeout(() => {
this.delayedRefresh = false;
this.loadMessages();
}, 500);
},
// handler for websocket message truncation
handleWSTruncate() {
// all messages deleted, go back to inbox
this.$router.push("/");
},
},
};
</script>
<template>
<div class="navbar navbar-expand-lg row flex-shrink-0 bg-primary text-white d-print-none" data-bs-theme="dark">
<div class="col-xl-2 col-md-3 col-auto pe-0">
<RouterLink to="/" class="navbar-brand text-white me-0" @click="pagination.start = 0">
<img :src="resolve('/mailpit.svg')" alt="Mailpit" />
<span class="ms-2 d-none d-sm-inline">Mailpit</span>
</RouterLink>
</div>
<div class="col col-md-4k col-lg-5 col-xl-6">
<SearchForm @load-messages="loadMessages" />
</div>
<div class="col-12 col-md-auto col-lg-4 col-xl-4 text-end mt-2 mt-lg-0">
<div class="float-start d-md-none">
<button
class="btn btn-outline-light me-2"
type="button"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvas"
aria-controls="offcanvas"
>
<i class="bi bi-list"></i>
</button>
</div>
<Pagination :total="mailbox.count" />
</div>
</div>
<div
id="offcanvas"
class="offcanvas-md offcanvas-start d-md-none"
data-bs-scroll="true"
tabindex="-1"
aria-labelledby="offcanvasLabel"
>
<div class="offcanvas-header">
<h5 id="offcanvasLabel" class="offcanvas-title">Mailpit</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="offcanvas"
data-bs-target="#offcanvas"
aria-label="Close"
></button>
</div>
<div class="offcanvas-body pb-0">
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 overflow-y-auto me-n3 pe-3">
<NavSearch @load-messages="loadMessages" />
<NavTags />
</div>
<About />
</div>
</div>
</div>
<div class="row flex-fill" style="min-height: 0">
<div class="d-none d-md-flex h-100 col-xl-2 col-md-3 flex-column">
<div class="flex-grow-1 overflow-y-auto me-n3 pe-3">
<NavSearch @load-messages="loadMessages" />
<NavTags />
</div>
<About />
</div>
<div class="col-xl-10 col-md-9 mh-100 ps-0 ps-md-2 pe-0">
<div id="message-page" class="mh-100" style="overflow-y: auto">
<ListMessages :loading-messages="loading" />
</div>
</div>
</div>
<NavSearch modals @load-messages="loadMessages" />
<About modals />
<AjaxLoader :loading="loading" />
</template>