Merge #1966
1966: AdminLTE3 optimizations & compression and caching r=mergify[bot] a=ghostwheel42 ## What type of PR? enhancement, bugfix ## What does this PR do? Optimization and cleanup of styles and javascript code for AdminLTE 3 Adds caching headers, gzip and robots.txt to nginx. ### Related issue(s) Makes #1800 even better. Thanks to `@DjVinnii` and `@Diman0` for the good work. Closes #1905 ## Prerequistes Before we can consider review and merge, please make sure the following list is done and checked. If an entry in not applicable, you can check it or remove it from the list. - [X] In case of feature or enhancement: documentation updated accordingly - [X] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/workflow.html#changelog) entry file. Co-authored-by: Alexander Graf <ghostwheel42@users.noreply.github.com> Co-authored-by: Dimitri Huisman <diman@huisman.xyz>master
@ -1,23 +1,54 @@
|
|||||||
.select2-search--inline .select2-search__field:focus {
|
/* mailu logo */
|
||||||
border: none;
|
.mailu-logo {
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
|
.bg-mailu-logo {
|
||||||
|
background-color: #2980b9!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar h4 {
|
/* user image */
|
||||||
padding-left: 5px;
|
.div-circle {
|
||||||
padding-right: 5px;
|
position: relative;
|
||||||
overflow: hidden;
|
width: 2.1rem;
|
||||||
text-overflow: ellipsis;
|
height: 2.1rem;
|
||||||
|
opacity: .8;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.div-circle > i {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-collapse .sidebar h4 {
|
/* nice round preformatted configuration display */
|
||||||
display: none !important;
|
.pre-config {
|
||||||
|
padding: 9px;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: anywhere;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo a {
|
/* fieldset */
|
||||||
color: #fff;
|
legend {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
fieldset:disabled :not(legend) label {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
fieldset:disabled .form-control:disabled {
|
||||||
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-toggle {
|
/* fix animation for icons in menu text */
|
||||||
padding: unset !important;
|
.sidebar .nav-link p i {
|
||||||
|
transition: margin-left .3s linear,opacity .3s ease,visibility .3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fix select2 text color */
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
@ -1,17 +1,70 @@
|
|||||||
require('./app.css');
|
require('./app.css');
|
||||||
|
|
||||||
import 'admin-lte/plugins/select2/js/select2.js';
|
import logo from './mailu.png';
|
||||||
import 'admin-lte/plugins/datatables/jquery.dataTables.js';
|
import modules from "./*.json";
|
||||||
import 'admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.js';
|
|
||||||
import 'admin-lte/plugins/datatables-responsive/js/dataTables.responsive.js';
|
|
||||||
import 'admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.js';
|
|
||||||
|
|
||||||
jQuery("document").ready(function() {
|
// TODO: conditionally (or lazy) load select2 and dataTable
|
||||||
jQuery(".mailselect").select2({
|
$('document').ready(function() {
|
||||||
|
|
||||||
|
// intercept anchors with data-clicked attribute and open alternate location instead
|
||||||
|
$('[data-clicked]').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
window.location.href = $(this).data('clicked');
|
||||||
|
});
|
||||||
|
|
||||||
|
// use post for language selection
|
||||||
|
$('#mailu-languages > a').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$.post({
|
||||||
|
url: $(this).attr('href'),
|
||||||
|
success: function() {
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// allow en-/disabling of inputs in fieldset with checkbox in legend
|
||||||
|
$('fieldset legend input[type=checkbox]').change(function() {
|
||||||
|
var fieldset = $(this).parents('fieldset');
|
||||||
|
if (this.checked) {
|
||||||
|
fieldset.removeAttr('disabled');
|
||||||
|
fieldset.find('input').not(this).removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
fieldset.attr('disabled', '');
|
||||||
|
fieldset.find('input').not(this).attr('disabled', '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// display of range input value
|
||||||
|
$('input[type=range]').each(function() {
|
||||||
|
var value_element = $('#'+this.id+'_value');
|
||||||
|
if (value_element.length) {
|
||||||
|
value_element = $(value_element[0]);
|
||||||
|
var infinity = $(this).data('infinity');
|
||||||
|
var step = $(this).attr('step');
|
||||||
|
$(this).on('input', function() {
|
||||||
|
value_element.text((infinity && this.value == 0) ? '∞' : this.value/step);
|
||||||
|
}).trigger('input');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// init select2
|
||||||
|
$('.mailselect').select2({
|
||||||
tags: true,
|
tags: true,
|
||||||
tokenSeparators: [',', ' ']
|
tokenSeparators: [',', ' '],
|
||||||
});
|
});
|
||||||
jQuery(".dataTable").DataTable({
|
|
||||||
"responsive": true,
|
// init dataTable
|
||||||
|
var d = $(document.documentElement);
|
||||||
|
$('.dataTable').DataTable({
|
||||||
|
'responsive': true,
|
||||||
|
language: {
|
||||||
|
url: d.data('static') + d.attr('lang') + '.json',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// init clipboard.js
|
||||||
|
new ClipboardJS('.btn-clip');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
@ -1,22 +1,24 @@
|
|||||||
// jQuery
|
|
||||||
import jQuery from 'jquery';
|
|
||||||
import 'admin-lte/plugins/select2/css/select2.css';
|
|
||||||
|
|
||||||
// bootstrap
|
|
||||||
// import 'bootstrap/less/bootstrap.less';
|
|
||||||
// import 'bootstrap';
|
|
||||||
|
|
||||||
// FontAwesome
|
|
||||||
import 'admin-lte/plugins/fontawesome-free/css/fontawesome.css';
|
|
||||||
import 'admin-lte/plugins/fontawesome-free/css/regular.css';
|
|
||||||
import 'admin-lte/plugins/fontawesome-free/css/solid.css';
|
|
||||||
|
|
||||||
// AdminLTE
|
// AdminLTE
|
||||||
|
import 'admin-lte/plugins/jquery/jquery.min.js';
|
||||||
|
import 'admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js';
|
||||||
import 'admin-lte/build/scss/adminlte.scss';
|
import 'admin-lte/build/scss/adminlte.scss';
|
||||||
import 'admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.css';
|
|
||||||
import 'admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.css';
|
|
||||||
import 'admin-lte/plugins/bootstrap/js/bootstrap.js';
|
|
||||||
import 'admin-lte/build/js/AdminLTE.js';
|
import 'admin-lte/build/js/AdminLTE.js';
|
||||||
import 'admin-lte/build/js/Layout.js';
|
|
||||||
import 'admin-lte/build/js/ControlSidebar.js';
|
// fontawesome plugin
|
||||||
import 'admin-lte/build/js/PushMenu.js';
|
import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
|
||||||
|
|
||||||
|
// select2 plugin
|
||||||
|
import 'admin-lte/plugins/select2/css/select2.min.css';
|
||||||
|
import 'admin-lte/plugins/select2/js/select2.min.js';
|
||||||
|
|
||||||
|
// dataTables plugin
|
||||||
|
import 'admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css';
|
||||||
|
import 'admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.min.css';
|
||||||
|
import 'admin-lte/plugins/datatables/jquery.dataTables.min.js';
|
||||||
|
import 'admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js';
|
||||||
|
import 'admin-lte/plugins/datatables-responsive/js/dataTables.responsive.min.js';
|
||||||
|
import 'admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.min.js';
|
||||||
|
|
||||||
|
// clipboard.js
|
||||||
|
import 'clipboard/dist/clipboard.min.js';
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Add a global administrator{% endtrans %}
|
{% trans %}Add a global administrator{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.admin, class_='mailselect') }}
|
{{ macros.form_field(form.admin, class_='mailselect') }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "alias/create.html" %}
|
{%- extends "alias/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit alias{% endtrans %}
|
{% trans %}Edit alias{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ alias }}
|
{{ alias }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Create alternative domain{% endtrans %}
|
{% trans %}Create alternative domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Public announcement{% endtrans %}
|
{% trans %}Public announcement{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.announcement_subject) }}
|
{{ macros.form_field(form.announcement_subject) }}
|
||||||
{{ macros.form_field(form.announcement_body, rows=10) }}
|
{{ macros.form_field(form.announcement_body, rows=10) }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
|
{%- block title %}
|
||||||
|
{% trans %}Antispam{% endtrans %}
|
||||||
|
{%- endblock %}
|
||||||
|
|
||||||
|
{%- block subtitle %}
|
||||||
|
{% trans %}RSPAMD status page{% endtrans %}
|
||||||
|
{%- endblock %}
|
||||||
|
|
||||||
|
{%- block content %}
|
||||||
|
<div class="embed-responsive embed-responsive-1by1">
|
||||||
|
<iframe class="embed-responsive-item" src="{{ config["WEB_ADMIN"] }}/antispam/"></iframe>
|
||||||
|
</div>
|
||||||
|
{%- endblock %}
|
@ -1,16 +1,16 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Confirm action{% endtrans %}
|
{% trans %}Confirm action{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ action }}
|
{{ action }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card(theme="warning") %}
|
{%- call macros.card(theme="warning") %}
|
||||||
<p>{% trans action %}You are about to {{ action }}. Please confirm your action.{% endtrans %}</p>
|
<p>{% trans action %}You are about to {{ action }}. Please confirm your action.{% endtrans %}</p>
|
||||||
{{ macros.form(form) }}
|
{{ macros.form(form) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Docker error{% endtrans %}
|
{% trans %}Docker error{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ action }}
|
{{ action }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<p>{% trans action %}An error occurred while talking to the Docker server.{% endtrans %}</p>
|
<p>{% trans action %}An error occurred while talking to the Docker server.{% endtrans %}</p>
|
||||||
<pre>{{ error }}</pre>
|
<pre class="pre-config border bg-light">{{ error }}</pre>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}New domain{% endtrans %}
|
{% trans %}New domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.name) }}
|
{{ macros.form_field(form.name) }}
|
||||||
{{ macros.form_fields((form.max_users, form.max_aliases)) }}
|
{{ macros.form_fields((form.max_users, form.max_aliases)) }}
|
||||||
{{ macros.form_field(form.max_quota_bytes, step=1000000000, max=50000000000,
|
{{ macros.form_field(form.max_quota_bytes, step=10**9, max=50*10**9, data_infinity="true",
|
||||||
prepend='<span class="input-group-text"><span id="quota">'+((form.max_quota_bytes.data//1000000000).__str__() if form.max_quota_bytes.data else '∞')+'</span> GiB</span>',
|
prepend='<span class="input-group-text"><span id="max_quota_bytes_value"></span> GB</span>') }}
|
||||||
oninput='$("#quota").text(this.value == 0 ? "∞" : this.value/1000000000);') }}
|
|
||||||
{{ macros.form_field(form.signup_enabled) }}
|
{{ macros.form_field(form.signup_enabled) }}
|
||||||
{{ macros.form_field(form.comment) }}
|
{{ macros.form_field(form.comment) }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,66 +1,69 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Domain details{% endtrans %}
|
{% trans %}Domain details{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain.name }}
|
{{ domain.name }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block main_action %}
|
{%- block main_action %}
|
||||||
{% if current_user.global_admin %}
|
{%- if current_user.global_admin %}
|
||||||
<a class="btn btn-primary float-right" href="{{ url_for(".domain_genkeys", domain_name=domain.name) }}">
|
<a class="btn btn-primary float-right" href="{{ url_for(".domain_genkeys", domain_name=domain.name) }}">
|
||||||
{% if domain.dkim_publickey %}
|
{%- if domain.dkim_publickey %}
|
||||||
{% trans %}Regenerate keys{% endtrans %}
|
{% trans %}Regenerate keys{% endtrans %}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{% trans %}Generate keys{% endtrans %}
|
{% trans %}Generate keys{% endtrans %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table(datatable=False) %}
|
{%- call macros.table(datatable=False) %}
|
||||||
{% set hostname = config["HOSTNAMES"].split(",")[0] %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Domain name{% endtrans %}</th>
|
<th>{% trans %}Domain name{% endtrans %}</th>
|
||||||
<td>{{ domain.name }}</td>
|
<td>{{ domain.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS MX entry{% endtrans %} <i class="fa {{ 'fa-check-circle' if domain.check_mx() else 'fa-exclamation-circle' }}"></i></th>
|
<th>{% trans %}DNS MX entry{% endtrans %} <i class="fa {{ 'fa-check-circle text-success' if domain.check_mx() else 'fa-exclamation-circle text-danger' }}"></i></th>
|
||||||
<td><pre>{{ domain.name }}. 600 IN MX 10 {{ hostname }}.</pre></td>
|
<td>{{ macros.clip("dns_mx") }}<pre id="dns_mx" class="pre-config border bg-light">{{ domain.dns_mx }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS SPF entries{% endtrans %}</th>
|
<th>{% trans %}DNS SPF entries{% endtrans %}</th>
|
||||||
<td><pre>
|
<td>{{ macros.clip("dns_spf") }}<pre id="dns_spf" class="pre-config border bg-light">{{ domain.dns_spf }}</pre>
|
||||||
{{ domain.name }}. 600 IN TXT "v=spf1 mx a:{{ hostname }} -all"</pre></td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if domain.dkim_publickey %}
|
{%- if domain.dkim_publickey %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DKIM public key{% endtrans %}</th>
|
<th>{% trans %}DKIM public key{% endtrans %}</th>
|
||||||
<td><pre style="white-space: pre-wrap; word-wrap: break-word;">{{ domain.dkim_publickey }}</pre></td>
|
<td>{{ macros.clip("dkim_key") }}<pre id="dkim_key" class="pre-config border bg-light">{{ domain.dkim_publickey }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS DKIM entry{% endtrans %}</th>
|
<th>{% trans %}DNS DKIM entry{% endtrans %}</th>
|
||||||
<td><pre style="white-space: pre-wrap; word-wrap: break-word;">{{ config["DKIM_SELECTOR"] }}._domainkey.{{ domain.name }}. 600 IN TXT "v=DKIM1; k=rsa; p={{ domain.dkim_publickey }}"</pre></td>
|
<td>{{ macros.clip("dns_dkim") }}<pre id="dns_dkim" class="pre-config border bg-light">{{ domain.dns_dkim }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS DMARC entry{% endtrans %}</th>
|
<th>{% trans %}DNS DMARC entry{% endtrans %}</th>
|
||||||
<td><pre>_dmarc.{{ domain.name }}. 600 IN TXT "v=DMARC1; p=reject;{% if config["DMARC_RUA"] %} rua=mailto:{{ config["DMARC_RUA"] }}@{{ config["DOMAIN"] }};{% endif %}{% if config["DMARC_RUF"] %} ruf=mailto:{{ config["DMARC_RUF"] }}@{{ config["DOMAIN"] }};{% endif %} adkim=s; aspf=s"</pre></td>
|
<td>{{ macros.clip("dns_dmark") }}<pre id="dns_dmark" class="pre-config border bg-light">{{ domain.dns_dmarc }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
|
{%- set tlsa_record=domain.dns_tlsa %}
|
||||||
|
{%- if tlsa_record %}
|
||||||
|
<tr>
|
||||||
|
<th>{% trans %}DNS TLSA entry{% endtrans %}</br><span class="text-secondary text-xs font-weight-normal">Let's Encrypt</br>ISRG Root X1</span></th>
|
||||||
|
<td>{{ macros.clip("dns_tlsa") }}<pre id="dns_tlsa" class="pre-config border bg-light">{{ tlsa_record }}</pre></td>
|
||||||
|
</tr>
|
||||||
|
{%- endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS client auto-configuration (RFC6186) entries{% endtrans %}</th>
|
<th>{% trans %}DNS client auto-configuration (RFC6186) entries{% endtrans %}</th>
|
||||||
<td>
|
<td>
|
||||||
<pre style="white-space: pre-wrap; word-wrap: break-word;">_submission._tcp.{{ domain.name }}. 600 IN SRV 1 1 587 {{ config["HOSTNAMES"].split(',')[0] }}.</pre>
|
{{ macros.clip("dns_autoconfig") }}<pre id="dns_autoconfig" class="pre-config border bg-light">
|
||||||
<pre style="white-space: pre-wrap; word-wrap: break-word;">_imap._tcp.{{ domain.name }}. 600 IN SRV 100 1 143 {{ config["HOSTNAMES"].split(',')[0] }}.</pre>
|
{%- for line in domain.dns_autoconfig %}
|
||||||
<pre style="white-space: pre-wrap; word-wrap: break-word;">_pop3._tcp.{{ domain.name }}. 600 IN SRV 100 1 110 {{ config["HOSTNAMES"].split(',')[0] }}.</pre>
|
{{ line }}
|
||||||
{% if config["TLS_FLAVOR"] != "notls" %}
|
{%- endfor -%}
|
||||||
<pre style="white-space: pre-wrap; word-wrap: break-word;">_submissions._tcp.{{ domain.name }}. 600 IN SRV 10 1 465 {{ config["HOSTNAMES"].split(',')[0] }}.</pre>
|
</pre></td>
|
||||||
<pre style="white-space: pre-wrap; word-wrap: break-word;">_imaps._tcp.{{ domain.name }}. 600 IN SRV 10 1 993 {{ config["HOSTNAMES"].split(',')[0] }}.</pre>
|
|
||||||
<pre style="white-space: pre-wrap; word-wrap: break-word;">_pop3s._tcp.{{ domain.name }}. 600 IN SRV 10 1 995 {{ config["HOSTNAMES"].split(',')[0] }}.</pre>
|
|
||||||
{% endif %}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "domain/create.html" %}
|
{%- extends "domain/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit domain{% endtrans %}
|
{% trans %}Edit domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Add a fetched account{% endtrans %}
|
{% trans %}Add a fetched account{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% call macros.card(title="Remote server") %}
|
{%- call macros.card(title="Remote server") %}
|
||||||
{{ macros.form_field(form.protocol) }}
|
{{ macros.form_field(form.protocol) }}
|
||||||
{{ macros.form_fields((form.host, form.port)) }}
|
{{ macros.form_fields((form.host, form.port)) }}
|
||||||
{{ macros.form_field(form.tls) }}
|
{{ macros.form_field(form.tls) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.card(title="Authentication") %}
|
{%- call macros.card(title="Authentication") %}
|
||||||
{{ macros.form_field(form.username) }}
|
{{ macros.form_field(form.username) }}
|
||||||
{{ macros.form_field(form.password) }}
|
{{ macros.form_field(form.password) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.card(title="Settings") %}
|
{%- call macros.card(title="Settings") %}
|
||||||
{{ macros.form_field(form.keep) }}
|
{{ macros.form_field(form.keep) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "fetch/create.html" %}
|
{%- extends "fetch/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Update a fetched account{% endtrans %}
|
{% trans %}Update a fetched account{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
{{ macros.form(form) }}
|
{{ macros.form(form) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Sign in{% endtrans %}
|
{% trans %}Sign in{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{% trans %}to access the administration tools{% endtrans %}
|
{% trans %}to access the administration tools{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,104 +1,127 @@
|
|||||||
{% macro form_errors(form) %}
|
{%- macro form_errors(form) %}
|
||||||
{% if form.errors %}
|
{%- if form.errors %}
|
||||||
{% for fieldname, errors in form.errors.items() %}
|
{%- for fieldname, errors in form.errors.items() %}
|
||||||
{% if bootstrap_is_hidden_field(form[fieldname]) %}
|
{%- if bootstrap_is_hidden_field(form[fieldname]) %}
|
||||||
{% for error in errors %}
|
{%- for error in errors %}
|
||||||
<p class="error">{{error}}</p>
|
<p class="error">{{error}}</p>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_field_errors(field) %}
|
{%- macro form_field_errors(field) %}
|
||||||
{% if field.errors %}
|
{%- if field.errors %}
|
||||||
{% for error in field.errors %}
|
{%- for error in field.errors %}
|
||||||
<p class="help-block inline">{{ error }}</p>
|
<p class="help-block inline">{{ error }}</p>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_fields(fields, prepend='', append='', label=True) %}
|
{%- macro form_fields(fields, prepend='', append='', label=True) %}
|
||||||
{% set width = (12 / fields|length)|int %}
|
{%- set width = (12 / fields|length)|int %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for field in fields %}
|
{%- for field in fields %}
|
||||||
<div class="col-lg-{{ width }} col-xs-12 {{ 'has-error' if field.errors else '' }}">
|
<div class="col-lg-{{ width }} col-xs-12 {{ 'has-error' if field.errors else '' }}">
|
||||||
{{ form_individual_field(field, prepend=prepend, append=append, label=label, **kwargs) }}
|
{{ form_individual_field(field, prepend=prepend, append=append, label=label, **kwargs) }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_individual_field(field, prepend='', append='', label=True, class_="") %}
|
{%- macro form_individual_field(field, prepend='', append='', label=True, class_="") %}
|
||||||
{% if field.type == "BooleanField" %}
|
{%- if field.type == "BooleanField" %}
|
||||||
{{ field(**kwargs) }}<span> </span>
|
{{ field(**kwargs) }}<span> </span>{{ field.label if label else '' }}
|
||||||
{{ field.label if label else '' }}
|
{%- else %}
|
||||||
{% else %}
|
|
||||||
{{ field.label if label else '' }}{{ form_field_errors(field) }}
|
{{ field.label if label else '' }}{{ form_field_errors(field) }}
|
||||||
{% if prepend %}<div class="input-group-prepend">{% endif %}
|
{%- if prepend %}<div class="input-group-prepend">{%- elif append %}<div class="input-group-append">{%- endif %}
|
||||||
{% if append %}<div class="input-group-append">{% endif %}
|
{{ prepend|safe }}{{ field(class_=("form-control " + class_) if class_ else "form-control", **kwargs) }}{{ append|safe }}
|
||||||
{{ prepend|safe }}{{ field(class_="form-control " + class_, **kwargs) }}{{ append|safe }}
|
{%- if prepend or append %}</div>{%- endif %}
|
||||||
{% if prepend or append %}</div>{% endif %}
|
{%- endif %}
|
||||||
{% endif %}
|
{%- endmacro %}
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro form_field(field) %}
|
{%- macro form_field(field) %}
|
||||||
{% if field.type == 'SubmitField' %}
|
{%- if field.type == 'SubmitField' %}
|
||||||
{{ form_fields((field,), label=False, class="btn btn-default", **kwargs) }}
|
{{- form_fields((field,), label=False, class="btn btn-default", **kwargs) }}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{{ form_fields((field,), **kwargs) }}
|
{{- form_fields((field,), **kwargs) }}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form(form) %}
|
{%- macro form(form) %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% for field in form %}
|
{%- for field in form %}
|
||||||
{% if bootstrap_is_hidden_field(field) %}
|
{%- if bootstrap_is_hidden_field(field) %}
|
||||||
{{ field() }}
|
{{ field() }}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{{ form_field(field) }}
|
{{ form_field(field) }}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
</form>
|
</form>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro card(title=None, theme="primary", header=True) %}
|
{%- macro card(title=None, theme="primary", header=True) %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="card card-outline card-{{ theme }}">
|
<div class="card card-outline card-{{ theme }}">
|
||||||
{% if header %}
|
{%- if header %}
|
||||||
<div class="card-header border-0">
|
<div class="card-header border-0">
|
||||||
{% if title %}
|
{%- if title %}
|
||||||
<h3 class="card-title">{{ title }}</h3>
|
<h3 class="card-title">{{ title }}</h3>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{{ caller() }}
|
{{- caller() }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro table(title=None, theme="primary", datatable=True) %}
|
{%- macro table(title=None, theme="primary", datatable=True) %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="card card-outline card-{{ theme }}">
|
<div class="card card-outline card-{{ theme }}">
|
||||||
|
{%- if title %}
|
||||||
<div class="card-header border-0">
|
<div class="card-header border-0">
|
||||||
{% if title %}
|
|
||||||
<h3 class="card-title">{{ title }}</h3>
|
<h3 class="card-title">{{ title }}</h3>
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
{%- endif %}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-bordered{% if datatable %} dataTable{% endif %}">
|
<table class="table table-bordered{% if datatable %} dataTable{% endif %}">
|
||||||
{{ caller() }}
|
{{- caller() }}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro fieldset(title=None, field=None, enabled=None, fields=None) %}
|
||||||
|
{%- if field or title %}
|
||||||
|
<fieldset{% if not enabled %} disabled{% endif %}>
|
||||||
|
{%- if field %}
|
||||||
|
<legend>{{ form_individual_field(field) }}</legend>
|
||||||
|
{%- else %}
|
||||||
|
<legend>{{ title }}</legend>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif %}
|
||||||
|
{{- caller() }}
|
||||||
|
{%- if fields %}
|
||||||
|
{%- set kwargs = {"enabled" if enabled else "disabled": ""} %}
|
||||||
|
{%- for field in fields %}
|
||||||
|
{{ form_field(field, **kwargs) }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endif %}
|
||||||
|
</fieldset>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro clip(target, title=_("copy to clipboard"), icon="copy", color="primary", action="copy") %}
|
||||||
|
<button class="btn btn-{{ color }} btn-xs btn-clip float-right ml-2 mt-1" data-clipboard-action="{{ action }}" data-clipboard-target="#{{ target }}">
|
||||||
|
<i class="fas fa-{{ icon }}" title="{{ title }}" aria-expanded="false"></i><span class="sr-only">{{ title }}</span>
|
||||||
|
</button>
|
||||||
|
{%- endmacro %}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Add a manager{% endtrans %}
|
{% trans %}Add a manager{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.manager, class_='mailselect') }}
|
{{ macros.form_field(form.manager, class_='mailselect') }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}New relay domain{% endtrans %}
|
{% trans %}New relay domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit relayd domain{% endtrans %}
|
{% trans %}Edit relayd domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ relay }}
|
{{ relay }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,144 +1,156 @@
|
|||||||
<div class="sidebar">
|
<div class="sidebar text-sm">
|
||||||
{% if current_user.is_authenticated %}
|
{%- if current_user.is_authenticated %}
|
||||||
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
|
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
|
||||||
|
<div class="image">
|
||||||
|
<div class="div-circle elevation-2"><i class="fa fa-user text-lg text-dark"></i></div>
|
||||||
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span class="text-center text-primary">{{ current_user }}</span>
|
<a href="{{ url_for('.user_settings') }}" class="d-block">{{ current_user }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
|
|
||||||
<nav class="mt-2">
|
<nav class="mt-2">
|
||||||
<ul class="nav nav-pills nav-sidebar flex-column" role="menu">
|
<ul class="nav nav-pills nav-sidebar flex-column" role="menu">
|
||||||
{% if current_user.is_authenticated %}
|
{%- if current_user.is_authenticated %}
|
||||||
<li class="nav-header">{% trans %}My account{% endtrans %}</li>
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}My account{% endtrans %}</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_settings') }}" class="nav-link">
|
<a href="{{ url_for('.user_settings') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fa fa-wrench"></i>
|
<i class="nav-icon fa fa-wrench"></i>
|
||||||
<p class="text">{% trans %}Settings{% endtrans %}</p>
|
<p>{% trans %}Settings{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_password') }}" class="nav-link">
|
<a href="{{ url_for('.user_password') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fa fa-lock"></i>
|
<i class="nav-icon fa fa-lock"></i>
|
||||||
<p class="text">{% trans %}Update password{% endtrans %}</p>
|
<p>{% trans %}Update password{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_reply') }}" class="nav-link">
|
<a href="{{ url_for('.user_reply') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fa fa-plane"></i>
|
<i class="nav-icon fa fa-plane"></i>
|
||||||
<p class="text">{% trans %}Auto-reply{% endtrans %}</p>
|
<p>{% trans %}Auto-reply{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.fetch_list') }}" class="nav-link">
|
<a href="{{ url_for('.fetch_list') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fas fa-download"></i>
|
<i class="nav-icon fas fa-download"></i>
|
||||||
<p class="text">{% trans %}Fetched accounts{% endtrans %}</p>
|
<p>{% trans %}Fetched accounts{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.token_list') }}" class="nav-link">
|
<a href="{{ url_for('.token_list') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fas fa-ticket-alt"></i>
|
<i class="nav-icon fas fa-ticket-alt"></i>
|
||||||
<p class="text">{% trans %}Authentication tokens{% endtrans %}</p>
|
<p>{% trans %}Authentication tokens{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{%- if current_user.is_authenticated %}
|
||||||
{% if current_user.manager_of or current_user.global_admin %}
|
<li class="nav-item" role="none">
|
||||||
<li class="nav-header">{% trans %}Administration{% endtrans %}</li>
|
<a href="{{ url_for('.client') }}" class="nav-link" role="menuitem">
|
||||||
{% endif %}
|
|
||||||
{% if current_user.global_admin %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ url_for('.announcement') }}" class="nav-link">
|
|
||||||
<i class="nav-icon fa fa-bullhorn"></i>
|
|
||||||
<p class="text">{% trans %}Announcement{% endtrans %}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ url_for('.admin_list') }}" class="nav-link">
|
|
||||||
<i class="nav-icon fa fa-user"></i>
|
|
||||||
<p class="text">{% trans %}Administrators{% endtrans %}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ url_for('.relay_list') }}" class="nav-link">
|
|
||||||
<i class="nav-icon fa fa-reply-all"></i>
|
|
||||||
<p class="text">{% trans %}Relayed domains{% endtrans %}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ config["WEB_ADMIN"] }}/antispam/" target="_blank" class="nav-link">
|
|
||||||
<i class="nav-icon fas fa-trash-alt"></i>
|
|
||||||
<p class="text">{% trans %}Antispam{% endtrans %}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if current_user.manager_of or current_user.global_admin %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ url_for('.domain_list') }}" class="nav-link">
|
|
||||||
<i class="nav-icon fa fa-envelope"></i>
|
|
||||||
<p class="text">{% trans %}Mail domains{% endtrans %}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<li class="nav-header">{% trans %}Go to{% endtrans %}</li>
|
|
||||||
{% if config["WEBMAIL"] != "none" %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ config["WEB_WEBMAIL"] }}" target="_blank" class="nav-link">
|
|
||||||
<i class="nav-icon far fa-envelope"></i>
|
|
||||||
<p class="text">{% trans %}Webmail{% endtrans %}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ url_for('.client') }}" class="nav-link">
|
|
||||||
<i class="nav-icon fa fa-laptop"></i>
|
<i class="nav-icon fa fa-laptop"></i>
|
||||||
<p class="text">{% trans %}Client setup{% endtrans %}</p>
|
<p>{% trans %}Client setup{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
{%- endif %}
|
||||||
<a href="{{ config["WEBSITE"] }}" target="_blank" class="nav-link">
|
|
||||||
|
{%- if current_user.manager_of or current_user.global_admin %}
|
||||||
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}Administration{% endtrans %}</li>
|
||||||
|
{%- endif %}
|
||||||
|
{%- if current_user.global_admin %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.announcement') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-bullhorn"></i>
|
||||||
|
<p>{% trans %}Announcement{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.admin_list') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-user"></i>
|
||||||
|
<p>{% trans %}Administrators{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.relay_list') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-reply-all"></i>
|
||||||
|
<p>{% trans %}Relayed domains{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ config["WEB_ADMIN"] }}/antispam/" data-clicked="{{ url_for('.antispam') }}" target="_blank" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fas fa-trash-alt"></i>
|
||||||
|
<p>{% trans %}Antispam{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
{%- if current_user.manager_of or current_user.global_admin %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.domain_list') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-envelope"></i>
|
||||||
|
<p>{% trans %}Mail domains{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}Go to{% endtrans %}</li>
|
||||||
|
{%- if config["WEBMAIL"] != "none" %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ config["WEB_WEBMAIL"] }}" target="_blank" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon far fa-envelope"></i>
|
||||||
|
<p>{% trans %}Webmail{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
{%- if not current_user.is_authenticated %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.client') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-laptop"></i>
|
||||||
|
<p>{% trans %}Client setup{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ config["WEBSITE"] }}" target="_blank" class="nav-link" role="menuitem" rel="noreferrer">
|
||||||
<i class="nav-icon fa fa-globe"></i>
|
<i class="nav-icon fa fa-globe"></i>
|
||||||
<p class="text">{% trans %}Website{% endtrans %}</p>
|
<p>{% trans %}Website{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="https://mailu.io" target="_blank" class="nav-link">
|
<a href="https://mailu.io" target="_blank" class="nav-link" role="menuitem" rel="noreferrer">
|
||||||
<i class="nav-icon fa fa-life-ring"></i>
|
<i class="nav-icon fa fa-life-ring"></i>
|
||||||
<p class="text">{% trans %}Help{% endtrans %}</p>
|
<p>{% trans %}Help{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if config['DOMAIN_REGISTRATION'] %}
|
{%- if config['DOMAIN_REGISTRATION'] %}
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.domain_signup') }}" class="nav-link">
|
<a href="{{ url_for('.domain_signup') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fa fa-plus-square"></i>
|
<i class="nav-icon fa fa-plus-square"></i>
|
||||||
<p class="text">{% trans %}Register a domain{% endtrans %}</p>
|
<p>{% trans %}Register a domain{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% if current_user.is_authenticated %}
|
{%- if current_user.is_authenticated %}
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.logout') }}" class="nav-link">
|
<a href="{{ url_for('.logout') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fas fa-sign-out-alt"></i>
|
<i class="nav-icon fas fa-sign-out-alt"></i>
|
||||||
<p class="text">{% trans %}Sign out{% endtrans %}</p>
|
<p>{% trans %}Sign out{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{%- else %}
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.login') }}" class="nav-link">
|
<a href="{{ url_for('.login') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fas fa-sign-in-alt"></i>
|
<i class="nav-icon fas fa-sign-in-alt"></i>
|
||||||
<p class="text">{% trans %}Sign in{% endtrans %}</p>
|
<p>{% trans %}Sign in{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if signup_domains %}
|
{%- if signup_domains %}
|
||||||
<li class="nav-item">
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_signup') }}" class="nav-link">
|
<a href="{{ url_for('.user_signup') }}" class="nav-link" role="menuitem">
|
||||||
<i class="nav-icon fa fa-user-plus"></i>
|
<i class="nav-icon fa fa-user-plus"></i>
|
||||||
<p class="text">{% trans %}Sign up{% endtrans %}</p>
|
<p>{% trans %}Sign up{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Create an authentication token{% endtrans %}
|
{% trans %}Create an authentication token{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,33 +1,32 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}New user{% endtrans %}
|
{% trans %}New user{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain.name }}
|
{{ domain.name }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
{% call macros.card(_("General")) %}
|
{%- call macros.card(_("General")) %}
|
||||||
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
||||||
{{ macros.form_fields((form.pw, form.pw2)) }}
|
{{ macros.form_fields((form.pw, form.pw2)) }}
|
||||||
{{ macros.form_field(form.displayed_name) }}
|
{{ macros.form_field(form.displayed_name) }}
|
||||||
{{ macros.form_field(form.comment) }}
|
{{ macros.form_field(form.comment) }}
|
||||||
{{ macros.form_field(form.enabled) }}
|
{{ macros.form_field(form.enabled) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.card(_("Features and quotas"), theme="success") %}
|
{%- call macros.card(_("Features and quotas"), theme="success") %}
|
||||||
{{ macros.form_field(form.quota_bytes, step=1000000000, max=(max_quota_bytes or domain.max_quota_bytes or 50000000000),
|
{{ macros.form_field(form.quota_bytes, step=1000000000, max=(max_quota_bytes or domain.max_quota_bytes or 50*10**9), data_infinity="true",
|
||||||
prepend='<span class="input-group-text"><span id="quota">'+((form.quota_bytes.data//1000000000).__str__() if form.quota_bytes.data else '∞')+'</span> GiB</span>',
|
prepend='<span class="input-group-text"><span id="quota_bytes_value"></span> GB</span>') }}
|
||||||
oninput='$("#quota").text(this.value == 0 ? "∞" : this.value/1000000000);') }}
|
|
||||||
{{ macros.form_field(form.enable_imap) }}
|
{{ macros.form_field(form.enable_imap) }}
|
||||||
{{ macros.form_field(form.enable_pop) }}
|
{{ macros.form_field(form.enable_pop) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "user/create.html" %}
|
{%- extends "user/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit user{% endtrans %}
|
{% trans %}Edit user{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
{% trans %}Forward emails{% endtrans %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block subtitle %}
|
|
||||||
{{ user }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% call macros.card() %}
|
|
||||||
<form class="form" method="post" role="form">
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
{{ macros.form_field(form.forward_enabled,
|
|
||||||
onchange="if(this.checked){$('#forward_destination,#forward_keep').removeAttr('disabled')}
|
|
||||||
else{$('#forward_destination,#forward_keep').attr('disabled', '')}") }}
|
|
||||||
{{ macros.form_field(form.forward_keep,
|
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
|
||||||
{{ macros.form_field(form.forward_destination,
|
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
|
||||||
{{ macros.form_field(form.submit) }}
|
|
||||||
</form>
|
|
||||||
{% endcall %}
|
|
||||||
{% endblock %}
|
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Password update{% endtrans %}
|
{% trans %}Password update{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,30 +1,23 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Automatic reply{% endtrans %}
|
{% trans %}Automatic reply{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.reply_enabled,
|
{%- call macros.fieldset(
|
||||||
onchange="if(this.checked){$('#reply_subject,#reply_body,#reply_enddate,#reply_startdate').removeAttr('readonly')}
|
field=form.reply_enabled,
|
||||||
else{$('#reply_subject,#reply_body,#reply_enddate,#reply_startdate').attr('readonly', '')}") }}
|
enabled=user.reply_enabled,
|
||||||
{{ macros.form_field(form.reply_subject,
|
fields=[form.reply_subject, form.reply_body, form.reply_enddate, form.reply_startdate]) %}
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
{%- endcall %}
|
||||||
{{ macros.form_field(form.reply_body, rows=10,
|
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
|
||||||
{{ macros.form_field(form.reply_enddate,
|
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
|
||||||
{{ macros.form_field(form.reply_startdate,
|
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,38 +1,36 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}User settings{% endtrans %}
|
{% trans %}User settings{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
{% call macros.card(title=_("Displayed name")) %}
|
{%- call macros.card(title=_("Displayed name")) %}
|
||||||
{{ macros.form_field(form.displayed_name) }}
|
{{ macros.form_field(form.displayed_name) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.card(title=_("Antispam")) %}
|
{%- call macros.card(title=_("Antispam")) %}
|
||||||
{{ macros.form_field(form.spam_enabled) }}
|
{%- call macros.fieldset(field=form.spam_enabled, enabled=user.spam_enabled) %}
|
||||||
{{ macros.form_field(form.spam_threshold, step=1, max=100,
|
{{ macros.form_field(form.spam_threshold, step=1, max=100,
|
||||||
prepend='<span class="input-group-text"><span id="threshold">'+form.spam_threshold.data.__str__()+'</span> / 100</span>',
|
prepend='<span class="input-group-text"><span id="spam_threshold_value"></span> / 100</span>') }}
|
||||||
oninput='$("#threshold").text(this.value);') }}
|
{%- endcall %}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.card(title=_("Auto-forward")) %}
|
{%- call macros.card(title=_("Auto-forward")) %}
|
||||||
{{ macros.form_field(form.forward_enabled,
|
{%- call macros.fieldset(
|
||||||
onchange="if(this.checked){$('#forward_destination,#forward_keep').removeAttr('disabled')}
|
field=form.forward_enabled,
|
||||||
else{$('#forward_destination,#forward_keep').attr('disabled', '')}") }}
|
enabled=user.forward_enabled,
|
||||||
{{ macros.form_field(form.forward_keep,
|
fields=[form.forward_keep, form.forward_destination]) %}
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
{%- endcall %}
|
||||||
{{ macros.form_field(form.forward_destination,
|
{%- endcall %}
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
|
||||||
{% endcall %}
|
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Sign up{% endtrans %}
|
{% trans %}Sign up{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% call macros.card() %}
|
{%- call macros.card() %}
|
||||||
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
||||||
{{ macros.form_fields((form.pw, form.pw2)) }}
|
{{ macros.form_fields((form.pw, form.pw2)) }}
|
||||||
{% if form.captcha %}
|
{%- if form.captcha %}
|
||||||
{{ macros.form_field(form.captcha) }}
|
{{ macros.form_field(form.captcha) }}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Sign up{% endtrans %}
|
{% trans %}Sign up{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{% trans %}pick a domain for the new account{% endtrans %}
|
{% trans %}pick a domain for the new account{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table() %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Domain{% endtrans %}</th>
|
<th>{% trans %}Domain{% endtrans %}</th>
|
||||||
<th>{% trans %}Available slots{% endtrans %}</th>
|
<th>{% trans %}Available slots{% endtrans %}</th>
|
||||||
<th>{% trans %}Quota{% endtrans %}</th>
|
<th>{% trans %}Quota{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for domain_name, domain in available_domains.items() %}
|
{%- for domain_name, domain in available_domains.items() %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url_for('.user_signup', domain_name=domain_name) }}">{{ domain_name }}</a></td>
|
<td><a href="{{ url_for('.user_signup', domain_name=domain_name) }}">{{ domain_name }}</a></td>
|
||||||
<td>{{ '∞' if domain.max_users == -1 else domain.max_users - (domain.users | count)}}</td>
|
<td>{{ '∞' if domain.max_users == -1 else domain.max_users - (domain.users | count)}}</td>
|
||||||
<td>{{ domain.max_quota_bytes or config['DEFAULT_QUOTA'] | filesizeformat }}</td>
|
<td>{{ domain.max_quota_bytes or config['DEFAULT_QUOTA'] | filesizeformat }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<div class="alert alert-warning" role="alert">{% trans %}We are still working on this feature!{% endtrans %}</div>
|
<div class="alert alert-warning" role="alert">{% trans %}We are still working on this feature!{% endtrans %}</div>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,65 +1,76 @@
|
|||||||
var path = require("path");
|
const path = require('path');
|
||||||
var webpack = require("webpack");
|
const webpack = require('webpack');
|
||||||
var css = require("mini-css-extract-plugin");
|
const css = require('mini-css-extract-plugin');
|
||||||
|
const mini = require('css-minimizer-webpack-plugin');
|
||||||
|
const terse = require('terser-webpack-plugin');
|
||||||
|
const compress = require('compression-webpack-plugin');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: "development",
|
mode: 'production',
|
||||||
entry: {
|
entry: {
|
||||||
app: "./assets/app.js",
|
app: {
|
||||||
vendor: "./assets/vendor.js"
|
import: './assets/app.js',
|
||||||
|
dependOn: 'vendor',
|
||||||
|
},
|
||||||
|
vendor: './assets/vendor.js',
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, "static/"),
|
path: path.resolve(__dirname, 'static/'),
|
||||||
filename: "[name].js"
|
filename: '[name].js',
|
||||||
|
assetModuleFilename: '[name][ext]',
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
use: ['babel-loader']
|
use: ['babel-loader', 'import-glob'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.scss$/,
|
test: /\.s?css$/i,
|
||||||
use: [css.loader, 'css-loader', 'sass-loader']
|
use: [css.loader, 'css-loader', 'sass-loader'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.less$/,
|
test: /\.less$/i,
|
||||||
use: [css.loader, 'css-loader', 'less-loader']
|
use: [css.loader, 'css-loader', 'less-loader'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.(json|png|svg|jpg|jpeg|gif)$/i,
|
||||||
use: [css.loader, 'css-loader']
|
type: 'asset/resource',
|
||||||
},
|
},
|
||||||
{
|
],
|
||||||
// Exposes jQuery for use outside Webpack build
|
|
||||||
test: require.resolve('jquery'),
|
|
||||||
use: [{
|
|
||||||
loader: 'expose-loader',
|
|
||||||
options: {
|
|
||||||
exposes: [
|
|
||||||
{
|
|
||||||
globalName: '$',
|
|
||||||
override: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
globalName: 'jQuery',
|
|
||||||
override: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new css({
|
new css({
|
||||||
filename: "[name].css",
|
filename: '[name].css',
|
||||||
chunkFilename: "[id].css"
|
chunkFilename: '[id].css',
|
||||||
}),
|
}),
|
||||||
new webpack.ProvidePlugin({
|
new webpack.ProvidePlugin({
|
||||||
$: "jquery",
|
$: 'jquery',
|
||||||
jQuery: "jquery"
|
jQuery: 'jquery',
|
||||||
})
|
ClipboardJS: 'clipboard',
|
||||||
]
|
}),
|
||||||
}
|
new compress({
|
||||||
|
filename: '[path][base].gz',
|
||||||
|
algorithm: "gzip",
|
||||||
|
exclude: /\.(png|gif|jpe?g)$/,
|
||||||
|
threshold: 5120,
|
||||||
|
minRatio: 0.8,
|
||||||
|
deleteOriginalAssets: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
optimization: {
|
||||||
|
minimize: true,
|
||||||
|
minimizer: [
|
||||||
|
new terse(),
|
||||||
|
new mini({
|
||||||
|
minimizerOptions: {
|
||||||
|
preset: [
|
||||||
|
'default', {
|
||||||
|
discardComments: { removeAll: true },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 978 B After Width: | Height: | Size: 924 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
@ -0,0 +1,33 @@
|
|||||||
|
AdminLTE3 design optimizations, asset compression and caching
|
||||||
|
|
||||||
|
- fixed copy of qemu-arm-static for alpine
|
||||||
|
- added 'set -eu' safeguard
|
||||||
|
- silenced npm update notification
|
||||||
|
- added color to webpack call
|
||||||
|
- changed Admin-LTE default blue
|
||||||
|
- AdminLTE 3 style tweaks
|
||||||
|
- localized datatables
|
||||||
|
- moved external javascript code to vendor.js
|
||||||
|
- added mailu logo
|
||||||
|
- moved all inline javascript to app.js
|
||||||
|
- added iframe display of rspamd page
|
||||||
|
- updated language-selector to display full language names and use post
|
||||||
|
- added fieldset to group and en/disable input fields
|
||||||
|
- added clipboard copy buttons
|
||||||
|
- cleaned external javascript imports
|
||||||
|
- pre-split first hostname for further use
|
||||||
|
- cache dns_* properties of domain object (immutable during runtime)
|
||||||
|
- fixed and splitted dns_dkim property of domain object (space missing)
|
||||||
|
- added autoconfig and tlsa properties to domain object
|
||||||
|
- suppressed extra vertical spacing in jinja2 templates
|
||||||
|
- improved accessibility for screen reader
|
||||||
|
- deleted unused/broken /user/forward route
|
||||||
|
- updated gunicorn to 20.1.0 to get rid of buffering error at startup
|
||||||
|
- switched webpack to production mode
|
||||||
|
- added css and javascript minimization
|
||||||
|
- added pre-compression of assets (gzip)
|
||||||
|
- removed obsolete dependencies
|
||||||
|
- switched from node-sass to dart-sass
|
||||||
|
- changed startup cleaning message from error to info
|
||||||
|
- move client config to "my account" section when logged in
|
||||||
|
|