Show more info in the email domains view
This commit is contained in:
@@ -1,30 +1,136 @@
|
||||
<script setup>
|
||||
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { prettyDecimalSize, sleep } from '@cloudron/pankow/utils';
|
||||
import Section from '../components/Section.vue';
|
||||
import StateLED from '../components/StateLED.vue';
|
||||
import DomainsModel from '../models/DomainsModel.js';
|
||||
import MailModel from '../models/MailModel.js';
|
||||
|
||||
const domainsModel = DomainsModel.create();
|
||||
const mailModel = MailModel.create();
|
||||
|
||||
const domains = ref([]);
|
||||
|
||||
async function refreshStatus() {
|
||||
for (const domain of domains.value) {
|
||||
const [error, result] = await mailModel.status(domain.domain);
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
domain.status = Object.keys(result).every((k) => {
|
||||
return result[k].status === 'passed' || result[k].status === 'skipped';
|
||||
});
|
||||
domain.loadingStatus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshUsage() {
|
||||
for (const domain of domains.value) {
|
||||
let [error, result] = await mailModel.config(domain.domain);
|
||||
if (error) return console.error(error);
|
||||
|
||||
domain.inboundEnabled = result.enabled;
|
||||
domain.outboundEnabled = result.relay?.provider !== 'noop';
|
||||
|
||||
// do this even if no outbound since people forget to remove mailboxes
|
||||
[error, result] = await mailModel.mailboxCount(domain.domain);
|
||||
if (error) console.error(error);
|
||||
|
||||
domain.mailboxCount = result;
|
||||
|
||||
// this may temporarily fail while the mail server is restarting
|
||||
while (true) {
|
||||
const [error, result] = await mailModel.usage(domain.domain);
|
||||
if (error && error.status === 424) {
|
||||
await sleep(1000);
|
||||
continue;
|
||||
} else if (error) return console.error(error);
|
||||
|
||||
domain.usage = 0;
|
||||
// we used to use quotaValue here but it's quite different wrt diskSize. so choose diskSize consistently
|
||||
// also, quotaValue can be missing for deleted mailboxes that are on disk but removed from dovecot/ldap itself
|
||||
Object.keys(result).forEach(function (m) { domain.usage += result[m].diskSize; });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
domain.loadingUsage = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const [error, result] = await domainsModel.list();
|
||||
if (error) return console.error(error);
|
||||
|
||||
result.forEach(d => {
|
||||
d.loadingStatus = true;
|
||||
d.status = {
|
||||
state: ''
|
||||
};
|
||||
|
||||
d.loadingUsage = true;
|
||||
d.mailboxCount = 0;
|
||||
d.usage = 0;
|
||||
d.inboundEnabled = true;
|
||||
d.outboundEnabled = true;
|
||||
});
|
||||
|
||||
domains.value = result;
|
||||
|
||||
refreshStatus();
|
||||
refreshUsage();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="content">
|
||||
<Section :title="$t('email.config.title')">
|
||||
<Section :title="$t('emails.domains.title')">
|
||||
<div>
|
||||
<div v-for="domain in domains" :key="domain.domain">
|
||||
<a :href="`#/email-domain/${domain.domain}`">{{ domain.domain }}</a>
|
||||
</div>
|
||||
<a v-for="domain in domains" :key="domain.domain" :href="`#/email-domain/${domain.domain}`" class="email-domain">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<StateLED :busy="domain.loadingStatus" :state="domain.status ? 'success' : 'danger'"/>
|
||||
</div>
|
||||
<div class="email-domain-details">
|
||||
<div><b style="font-size: 16px">{{ domain.domain }}</b></div>
|
||||
<div v-if="domain.loadingUsage">
|
||||
{{ $t('main.loadingPlaceholder') }} ...
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="domain.inboundEnabled">
|
||||
{{ $t('emails.domains.stats', { mailboxCount: domain.mailboxCount, usage: prettyDecimalSize(domain.usage) }) }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<span v-if="domain.outboundEnabled">{{ $t('emails.domains.outbound') }}</span>
|
||||
<span v-else>{{ $t('emails.domains.disabled') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.email-domain {
|
||||
display: flex;
|
||||
border-radius: var(--pankow-border-radius);
|
||||
padding: 10px;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
color: var(--pankow-text-color);
|
||||
}
|
||||
|
||||
.email-domain:hover {
|
||||
background-color: var(--pankow-color-background-hover);
|
||||
}
|
||||
|
||||
.email-domain-details {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user