Split up Email views
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
<script setup>
|
||||
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { eachLimit } from 'async';
|
||||
import { Button } from 'pankow';
|
||||
import { prettyDecimalSize } from 'pankow/utils';
|
||||
import Section from '../components/Section.vue';
|
||||
import StateLED from '../components/StateLED.vue';
|
||||
import MailDomainStatus from '../components/MailDomainStatus.vue';
|
||||
import DomainsModel from '../models/DomainsModel.js';
|
||||
import MailModel from '../models/MailModel.js';
|
||||
|
||||
const domainsModel = DomainsModel.create();
|
||||
const mailModel = MailModel.create();
|
||||
|
||||
const refreshBusy = ref(true);
|
||||
const domains = ref([]);
|
||||
const expandedDomain = ref('');
|
||||
|
||||
async function onRefresh() {
|
||||
refreshBusy.value = true;
|
||||
await eachLimit(domains.value, 10, refreshStatus);
|
||||
refreshBusy.value = false;
|
||||
}
|
||||
|
||||
async function refreshStatus(domain) {
|
||||
let [error, result] = await mailModel.status(domain.domain);
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
domain.status = Object.keys(result).every((k) => {
|
||||
if (k === 'dns') return Object.keys(result.dns).every(function (k) { return result.dns[k].status; });
|
||||
if (!('status' in result[k])) return true; // if status is not present, the test was not run
|
||||
return result[k].status;
|
||||
});
|
||||
domain.statusCheckDone = true;
|
||||
}
|
||||
|
||||
[error, result] = await mailModel.config(domain.domain);
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
domain.inbound = result.enabled;
|
||||
domain.outbound = 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);
|
||||
} else {
|
||||
domain.mailboxCount = result;
|
||||
}
|
||||
|
||||
domain.loading = false;
|
||||
|
||||
// TODO
|
||||
// mail usage is loaded separately with a cancellation check. when there are a lot of domains, it runs a long time in background and slows down loading of new views
|
||||
[error, result] = await mailModel.usage(domain.domain);
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
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; });
|
||||
domain.loadingUsage = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onToggleExpanded(domain) {
|
||||
expandedDomain.value = expandedDomain.value === domain ? '' : domain;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const [error, result] = await domainsModel.list();
|
||||
if (error) return console.error(error);
|
||||
|
||||
domains.value = result;
|
||||
|
||||
onRefresh();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="content">
|
||||
<Section title="Mail domain status">
|
||||
<template #header-buttons>
|
||||
<Button @click="onRefresh" :disabled="refreshBusy" :loading="refreshBusy">Refresh</Button>
|
||||
</template>
|
||||
|
||||
<div class="domain-list-item" :class="{ active: domain.domain === expandedDomain }" v-for="domain in domains" :key="domain.domain">
|
||||
<div @click="onToggleExpanded(domain.domain)" style="display: flex; justify-content: space-between;">
|
||||
<div>
|
||||
<StateLED :busy="!domain.statusCheckDone" :state="domain.status ? 'success' : 'danger'" style="margin-right: 6px"/>
|
||||
{{ domain.domain }}
|
||||
</div>
|
||||
|
||||
<div v-if="domain.loading">{{ $t('main.loadingPlaceholder') }} ...</div>
|
||||
<div v-else>
|
||||
<div v-if="domain.inbound">
|
||||
<span v-if="domain.loadingUsage">{{ $t('emails.domains.stats', { mailboxCount: domain.mailboxCount }) }} {{ $t('main.loadingPlaceholder') }} ... </span>
|
||||
<span v-else>{{ $t('emails.domains.stats', { mailboxCount: domain.mailboxCount, usage: prettyDecimalSize(domain.usage) }) }}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span v-if="domain.outbound">{{ $t('emails.domains.outbound') }}</span>
|
||||
<span v-else>{{ $t('emails.domains.disabled') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MailDomainStatus :domain="domain.domain" v-if="expandedDomain === domain.domain"/>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.domain-list-item {
|
||||
cursor: pointer;
|
||||
padding: 10px 0;
|
||||
border-radius: var(--pankow-border-radius);
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.domain-list-item.active,
|
||||
.domain-list-item:hover {
|
||||
background-color: var(--pankow-color-background-hover);
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user