7a5e990ad4
we start a bunch of requests in the background for each domain. when we switch views immediately, to say the eventlog, these requests are still active in the background. canceling the requests will require a much bigger refactor. https://forum.cloudron.io/topic/10434/email-event-log-loading-very-slowly-seems-tied-to-overall-email-domain-list-health-checks
365 lines
20 KiB
HTML
365 lines
20 KiB
HTML
<!-- Modal change max email size -->
|
|
<div class="modal fade" id="maxEmailSizeChangeModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'emails.changeMailSizeDialog.title' | tr }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div ng-bind-html=" 'emails.changeMailSizeDialog.description' | tr "></div>
|
|
<br>
|
|
<form name="maxEmailSizeChangeForm" role="form" novalidate ng-submit="maxEmailSize.submit()" autocomplete="off">
|
|
<div class="form-group">
|
|
<label class="control-label">{{ 'emails.changeMailSizeDialog.size' | tr }} <b>{{ maxEmailSize.size | prettyDecimalSize }}</b></label>
|
|
<slider ng-model="maxEmailSize.size" tooltip="hide" min="1000000" max="1000000000" step="1000000"></slider>
|
|
</div>
|
|
<input class="ng-hide" type="submit"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="button" class="btn btn-success" ng-click="maxEmailSize.submit()" ng-disabled="maxEmailSize.size === maxEmailSize.currentSize"><i class="fa fa-circle-notch fa-spin" ng-show="maxEmailSize.busy"></i> {{ 'main.dialog.save' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal change virtual all mail -->
|
|
<div class="modal fade" id="virtualAllMailChangeModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'emails.changeVirtualAllMailDialog.title' | tr }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div ng-bind-html=" 'emails.changeVirtualAllMailDialog.description' | tr "></div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button class="btn btn-primary" ng-click="virtualAllMail.submit(!virtualAllMail.enabled)"><i class="fa fa-circle-notch fa-spin" ng-show="virtualAllMail.busy"></i> {{ virtualAllMail.enabled ? ('main.disableAction' | tr) : ('main.enableAction' | tr) }} </button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal solr config -->
|
|
<div class="modal fade" id="solrConfigModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'emails.solrConfig.title' | tr }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p ng-bind-html=" 'emails.solrConfig.description' | tr "></p>
|
|
<!-- only show this when user is trying to enable -->
|
|
<p class="has-error" ng-show="!solrConfig.currentConfig.enabled && !solrConfig.enoughMemory">{{ 'emails.solrConfig.notEnoughMemory' | tr }}</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
|
<button type="button" class="btn btn-success" ng-hide="solrConfig.currentConfig.enabled" ng-click="solrConfig.submit(true)" ng-disabled="(!solrConfig.currentConfig.enabled && !solrConfig.enoughMemory) || solrConfig.busy"><i class="fa fa-circle-notch fa-spin" ng-show="solrConfig.busy"></i> {{ 'main.enableAction' | tr }}</button>
|
|
<button type="button" class="btn btn-danger" ng-show="solrConfig.currentConfig.enabled" ng-click="solrConfig.submit(false)" ng-disabled="solrConfig.busy"><i class="fa fa-circle-notch fa-spin" ng-show="solrConfig.busy"></i> {{ 'main.disableAction' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal change acl -->
|
|
<div class="modal fade" id="aclChangeModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'emails.aclDialog.title' | tr }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="aclChangeForm" role="form" novalidate ng-submit="acl.submit()" autocomplete="off">
|
|
<div class="form-group">
|
|
<label class="control-label">{{ 'emails.aclDialog.dnsblZones' | tr }} <sup><a ng-href="https://docs.cloudron.io/email/#dnsbl" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
|
<p class="small">{{ 'emails.aclDialog.dnsblZonesInfo' | tr }}</p>
|
|
<div class="has-error" ng-show="acl.error.dnsblZones">{{ acl.error.dnsblZones }}</div>
|
|
<textarea ng-model="acl.dnsblZones" placeholder="{{ 'emails.aclDialog.dnsblZonesPlaceholder' | tr }}" name="dnsblZones" class="form-control" ng-class="{ 'has-error': !aclChangeForm.dnsblZones.$dirty && acl.error.dnsblZones }" rows="4"></textarea>
|
|
</div>
|
|
<input class="ng-hide" type="submit"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="button" class="btn btn-success" ng-click="acl.submit()"><i class="fa fa-circle-notch fa-spin" ng-show="acl.busy"></i> {{ 'main.dialog.save' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal change spam config -->
|
|
<div class="modal fade" id="spamConfigChangeModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'emails.spamFilterDialog.title' | tr }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="spamConfigChangeForm" role="form" novalidate ng-submit="spamConfig.submit()" autocomplete="off">
|
|
<div class="form-group">
|
|
<label class="control-label">{{ 'emails.spamFilterDialog.blacklisteAddresses' | tr }}</label>
|
|
<p class="small">{{ 'emails.spamFilterDialog.blacklisteAddressesInfo' | tr }}</p>
|
|
<div class="has-error" ng-show="spamConfig.error.blacklist">{{ spamConfig.error.blacklist }}</div>
|
|
<textarea ng-model="spamConfig.blacklist" placeholder="{{ 'emails.spamFilterDialog.blacklisteAddressesPlaceholder' | tr }}" name="blacklist" class="form-control" ng-class="{ 'has-error': !spamConfigChangeForm.blacklist.$dirty && spamConfig.error.blacklist }" rows="4"></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label">{{ 'emails.spamFilterDialog.customRules' | tr }} <sup><a ng-href="https://docs.cloudron.io/email/#custom-spam-filtering-rules" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
|
<div class="has-error" ng-show="spamConfig.error.config">{{ spamConfig.error.config }}</div>
|
|
<textarea ng-model="spamConfig.config" placeholder="{{ 'emails.spamFilterDialog.customRulesPlaceholder' | tr }}" class="form-control" name="config" ng-class="{ 'has-error': !spamConfigChangeForm.config.$dirty && spamConfig.error.config }" rows="4"></textarea>
|
|
</div>
|
|
<input class="ng-hide" type="submit"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="button" class="btn btn-success" ng-click="spamConfig.submit()"><i class="fa fa-circle-notch fa-spin" ng-show="spamConfig.busy"></i> {{ 'main.dialog.save' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Test email -->
|
|
<div class="modal fade" id="testEmailModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'emails.testMailDialog.title' | tr:{ domain: testEmail.domain.domain } }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="testEmailForm" role="form" novalidate ng-submit="testEmail.submit()" autocomplete="off">
|
|
<fieldset>
|
|
<p class="has-error text-center" ng-show="testEmail.error">{{ testEmail.error.generic }}</p>
|
|
<p ng-bind-html="'emails.testMailDialog.description' | tr:{ domain: testEmail.domain.domain }"></p>
|
|
<br/>
|
|
<div class="form-group" ng-class="{ 'has-error': testEmail.error.key }">
|
|
<label class="control-label" for="inputTestEmailKey">{{ 'emails.testMailDialog.mailTo' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="testEmail.mailTo" id="inputTestMailTo" name="mailTo" ng-disabled="testEmail.busy" placeholder="{{ 'emails.testMailDialog.mailToPlaceholder' | tr }}" autofocus>
|
|
</div>
|
|
|
|
<input class="ng-hide" type="submit" ng-disabled="testEmailForm.$invalid"/>
|
|
</fieldset>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer ">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="testEmail.submit()" ng-disabled="testEmail.$invalid || testEmail.busy"><i class="fa fa-circle-notch fa-spin" ng-show="testEmail.busy"></i> {{ 'emails.testMailDialog.sendAction' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content">
|
|
<div class="text-left">
|
|
<h1>
|
|
{{ 'emails.title' | tr }}
|
|
|
|
<div class="pull-right">
|
|
<a class="btn btn-default" ng-show="user.isAtLeastAdmin" href="#/emails-queue">{{ 'emails.action.queue' | tr }}</a>
|
|
<a class="btn btn-default" ng-show="user.isAtLeastAdmin" href="#/emails-eventlog">{{ 'eventlog.title' | tr }}</a>
|
|
</div>
|
|
</h1>
|
|
</div>
|
|
|
|
<!-- domain listing -->
|
|
<div class="text-left">
|
|
<h3>{{ 'emails.domains.title' | tr }}</h3>
|
|
</div>
|
|
|
|
<div class="card" style="margin-bottom: 15px;">
|
|
<div class="row ng-hide" ng-hide="ready">
|
|
<div class="col-lg-12 text-center">
|
|
<h2><i class="fa fa-circle-notch fa-spin"></i></h2>
|
|
</div>
|
|
</div>
|
|
<div class="row animateMeOpacity ng-hide" ng-show="ready">
|
|
<div class="col-xs-12">
|
|
<table class="table table-hover" style="margin: 0;">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 5%"></th>
|
|
<th style="width: 30%">{{ 'emails.domains.domain' | tr }}</th>
|
|
<th style="width: 60%">{{ 'emails.domains.config' | tr }}</th>
|
|
<th style="width: 10%">{{ 'main.actions' | tr }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="domain in domains">
|
|
<td>
|
|
<i class="fa fa-circle" ng-class="{ 'status-active': domain.statusOk, 'status-error': !domain.statusOk }" ng-show="domain.status"></i>
|
|
<i class="fa fa-circle-notch fa-spin" ng-hide="domain.status"></i>
|
|
</td>
|
|
<td class="elide-table-cell no-padding">
|
|
<a href="/#/email/{{ domain.domain }}" class="email-domain-list-item">{{ domain.domain }}</a>
|
|
</td>
|
|
<td class="elide-table-cell no-padding">
|
|
<a href="/#/email/{{ domain.domain }}" class="email-domain-list-item">
|
|
<span ng-switch on="domain.loading">
|
|
<span ng-switch-when="true">{{ 'main.loadingPlaceholder' | tr }} ...</span>
|
|
<span ng-switch-default>
|
|
<span ng-switch on="domain.inbound">
|
|
<span ng-switch-when="true">
|
|
<span ng-show="domain.loadingUsage">{{ 'emails.domains.stats' | tr:{ mailboxCount: domain.mailboxCount } }} {{ 'main.loadingPlaceholder' | tr }} ... </span>
|
|
<span ng-show="!domain.loadingUsage">{{ 'emails.domains.stats' | tr:{ mailboxCount: domain.mailboxCount, usage: (domain.usage | prettyDecimalSize) } }}</span>
|
|
</span>
|
|
<span ng-switch-default>
|
|
<span ng-show="domain.outbound">{{ 'emails.domains.outbound' | tr }}</span>
|
|
<span ng-show="!domain.outbound">{{ 'emails.domains.disabled' | tr }}</span>
|
|
</span>
|
|
</span>
|
|
</span>
|
|
</a>
|
|
</td>
|
|
<td class="text-right no-wrap">
|
|
<button class="btn btn-xs btn-default" ng-click="testEmail.show(domain)" uib-tooltip="{{ 'emails.domains.testEmailTooltip' | tr }}"><i class="fa fa-paper-plane"></i></button>
|
|
<a href="/#/email/{{ domain.domain }}" class="btn btn-xs btn-default"><i class="fa fa-pencil-alt"></i></a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- mailbox sharing -->
|
|
<div class="text-left section-header" ng-show="user.isAtLeastAdmin">
|
|
<h3>{{ 'emails.mailboxSharing.title' | tr }}</h3>
|
|
</div>
|
|
|
|
<div class="card" ng-show="user.isAtLeastAdmin" style="margin-bottom: 15px;">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<p>{{ 'emails.mailboxSharing.description' | tr }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-2" style="padding-top: 12px;">
|
|
<i class="fa fa-circle" ng-class="{ 'status-active': mailboxSharing.enabled, 'status-inactive': !mailboxSharing.enabled }"></i> {{ mailboxSharing.enabled ? 'main.statusEnabled' : 'main.statusDisabled' | tr }}
|
|
</div>
|
|
<div class="col-md-10 text-right">
|
|
<button class="btn" ng-class="{ 'btn-danger': mailboxSharing.enabled, 'btn-primary': !mailboxSharing.enabled }" ng-click="mailboxSharing.submit()" ng-disabled="mailboxSharing.enable === mailboxSharing.enabled"><i class="fa fa-circle-notch fa-spin" ng-show="mailboxSharing.busy"></i> {{ mailboxSharing.enabled ? ('main.disableAction' | tr) : ('main.enableAction' | tr) }} </button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- server location -->
|
|
<div class="text-left section-header" ng-show="user.isAtLeastAdmin">
|
|
<h3>
|
|
{{ 'emails.settings.location' | tr }}
|
|
<div class="btn-group btn-group-sm pull-right">
|
|
<button type="button" class="btn btn-small btn-default dropdown-toggle" ng-show="mailLocation.tasks.length" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" uib-tooltip="{{ 'main.action.showLogs' | tr }}">
|
|
<i class="fas fa-align-left"></i> <span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li ng-repeat="task in mailLocation.tasks">
|
|
<a ng-href="/frontend/logs.html?taskId={{task.id}}" target="_blank" class="text-right">
|
|
{{ task.ts | prettyLongDate }} <i class="fa" style="margin-left: 20px" ng-class="{ 'status-active fa-check-circle': !task.active && task.success, 'fa-circle-notch fa-spin': task.active, 'status-error fa-times-circle': !task.active && !task.success }"></i>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="row">
|
|
<div class="col-md-7">
|
|
<p ng-bind-html="'emails.changeDomainDialog.description' | tr"></p>
|
|
</div>
|
|
<div class="col-md-5">
|
|
<div class="input-group form-inline">
|
|
<input type="text" class="form-control" ng-model="mailLocation.subdomain" id="mailLocationLocationInput" name="location" placeholder="{{ 'emails.changeDomainDialog.locationPlaceholder' | tr }}" autofocus>
|
|
|
|
<div class="input-group-btn">
|
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
|
<span>{{ (!mailLocation.subdomain ? '' : '.') + mailLocation.domain.domain }}</span>
|
|
<span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
|
<li ng-repeat="domain in domains">
|
|
<a href="" ng-click="mailLocation.domain = domain">{{ domain.domain }}</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12" style="margin-bottom: 10px;">
|
|
<div ng-show="mailLocation.busy" class="progress progress-striped active animateMe">
|
|
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ mailLocation.percent }}%"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="text-center text-warning text-bold" ng-show="mailLocation.domain.provider === 'manual'" ng-bind-html="'emails.changeDomainDialog.manualInfo' | tr:{ domain: mailLocation.domain.domain }"></p>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<p ng-show="mailLocation.busy">{{ mailLocation.message }}</p>
|
|
<p ng-hide="mailLocation.busy">
|
|
<div class="has-error" ng-show="!mailLocation.active">{{ mailLocation.errorMessage }}</div>
|
|
</p>
|
|
</div>
|
|
<div class="col-md-6 text-right">
|
|
<!-- save is always enabled so that user can "redo" the task -->
|
|
<button class="btn btn-outline btn-primary" ng-click="mailLocation.change()" ng-hide="mailLocation.busy">{{ 'main.dialog.save' | tr }}</button>
|
|
<button class="btn btn-outline btn-danger" ng-click="mailLocation.stop()" ng-show="mailLocation.busy" style="margin-right: 10px">{{ 'main.dialog.cancel' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- settings -->
|
|
<div class="text-left section-header" ng-show="user.isAtLeastAdmin">
|
|
<h3>{{ 'emails.settings.title' | tr }}</h3>
|
|
</div>
|
|
|
|
<div class="card" ng-show="user.isAtLeastAdmin" style="margin-bottom: 15px;">
|
|
<p ng-bind-html=" 'emails.settings.info' | tr "></p>
|
|
<div class="row">
|
|
<div class="col-xs-6">
|
|
<span class="text-muted">{{ 'emails.settings.maxMailSize' | tr }}</span>
|
|
</div>
|
|
<div class="col-xs-6 text-right">
|
|
<span>{{ maxEmailSize.currentSize | prettyDecimalSize }} <a href="" ng-click="maxEmailSize.show()"><i class="fa fa-edit text-small"></i></a></span>
|
|
</div>
|
|
<div class="col-xs-6">
|
|
<span class="text-muted">{{ 'emails.settings.virtualAllMail' | tr }}</span>
|
|
</div>
|
|
<div class="col-xs-6 text-right">
|
|
<span>{{ virtualAllMail.enabled ? 'main.statusEnabled' : 'main.statusDisabled' | tr }} <a href="" ng-click="virtualAllMail.show()"><i class="fa fa-edit text-small"></i></a></span>
|
|
</div>
|
|
<div class="col-xs-6">
|
|
<span class="text-muted">{{ 'emails.settings.acl' | tr }}</span>
|
|
</div>
|
|
<div class="col-xs-6 text-right">
|
|
<span>{{ 'emails.settings.aclOverview' | tr:{ dnsblZonesCount: acl.dnsblZonesCount } }} <a href="" ng-click="acl.show()"><i class="fa fa-edit text-small"></i></a></span>
|
|
</div>
|
|
<div class="col-xs-6">
|
|
<span class="text-muted">{{ 'emails.settings.spamFilter' | tr }}</span>
|
|
</div>
|
|
<div class="col-xs-6 text-right">
|
|
<span>{{ 'emails.settings.spamFilterOverview' | tr:{ blacklistCount: spamConfig.acl.blacklist.length } }} <a href="" ng-click="spamConfig.show()"><i class="fa fa-edit text-small"></i></a></span>
|
|
</div>
|
|
<div class="col-xs-6">
|
|
<span class="text-muted">{{ 'emails.settings.solrFts' | tr }}</span>
|
|
</div>
|
|
<div class="col-xs-6 text-right" ng-hide="solrConfig.currentConfig">
|
|
<i class="fa fa-circle-notch fa-spin"></i>
|
|
</div>
|
|
<div class="col-xs-6 text-right" ng-show="solrConfig.currentConfig">
|
|
<span ng-show="solrConfig.currentConfig.enabled">
|
|
{{ 'emails.settings.solrEnabled' | tr }}
|
|
<span ng-show="solrConfig.running">/ {{ 'emails.settings.solrRunning' | tr }}</span>
|
|
<span ng-hide="solrConfig.running">/ {{ 'emails.settings.solrNotRunning' | tr }}</span>
|
|
</span>
|
|
<span ng-hide="solrConfig.currentConfig.enabled">{{ 'emails.settings.solrDisabled' | tr }}</span>
|
|
<a href="" ng-click="solrConfig.show()"><i class="fa fa-edit text-small"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|