Customize SOGo theme from Web UI
This commit is contained in:
@@ -103,9 +103,12 @@ $template_data = [
|
||||
'rsettings' => $rsettings,
|
||||
'rspamd_regex_maps' => $rspamd_regex_maps,
|
||||
'logo_specs' => customize('get', 'main_logo_specs'),
|
||||
'favicon_specs' => customize('get', 'favicon_specs'),
|
||||
'ip_check' => customize('get', 'ip_check'),
|
||||
'password_complexity' => password_complexity('get'),
|
||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||
'sogo_palettes' => $GLOBALS['SOGO_PALETTES'],
|
||||
'sogo_theme' => customize('get', 'sogo_theme'),
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
'lang_datatables' => json_encode($lang['datatables'])
|
||||
];
|
||||
|
@@ -5602,6 +5602,109 @@ paths:
|
||||
description: You can list all mailboxes existing in system for a specific domain.
|
||||
operationId: Get mailboxes of a domain
|
||||
summary: Get mailboxes of a domain
|
||||
/api/v1/edit/sogo_theme/:
|
||||
post:
|
||||
responses:
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
- type: success
|
||||
log:
|
||||
- customize
|
||||
- edit
|
||||
- sogo_theme
|
||||
- primary: "brown"
|
||||
accent: "brown"
|
||||
background: "amber"
|
||||
msg:
|
||||
- sogo_theme_modified
|
||||
schema:
|
||||
properties:
|
||||
log:
|
||||
description: contains request object
|
||||
items: {}
|
||||
type: array
|
||||
msg:
|
||||
items: {}
|
||||
type: array
|
||||
type:
|
||||
enum:
|
||||
- success
|
||||
- danger
|
||||
- error
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
headers: {}
|
||||
tags:
|
||||
- Customize
|
||||
description: >-
|
||||
Using this endpoint you can edit the sogo theme. SOGo has to be restarted after each change.
|
||||
operationId: Edit SOGo theme
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
example:
|
||||
primary: "brown"
|
||||
accent: "brown"
|
||||
background: "amber"
|
||||
summary: Edit SOGo theme
|
||||
/api/v1/delete/sogo_theme/:
|
||||
post:
|
||||
responses:
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
- type: success
|
||||
log:
|
||||
- customize
|
||||
- delete
|
||||
- sogo_theme
|
||||
- items:
|
||||
- sogo-theme
|
||||
msg: "sogo_theme_removed"
|
||||
schema:
|
||||
properties:
|
||||
log:
|
||||
description: contains request object
|
||||
items: {}
|
||||
type: array
|
||||
msg:
|
||||
items: {}
|
||||
type: array
|
||||
type:
|
||||
enum:
|
||||
- success
|
||||
- danger
|
||||
- error
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
headers: {}
|
||||
tags:
|
||||
- Customize
|
||||
description: >-
|
||||
Using this endpoint you can reset the sogo theme. SOGo has to be restarted after each change.
|
||||
operationId: Reset SOGo theme
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
example:
|
||||
- items:
|
||||
- "sogo-theme"
|
||||
summary: Reset SOGo theme
|
||||
|
||||
tags:
|
||||
- name: Domains
|
||||
@@ -5646,3 +5749,5 @@ tags:
|
||||
description: Get the status of your cow
|
||||
- name: Ratelimits
|
||||
description: Edit domain ratelimits
|
||||
- name: Customize
|
||||
description: You can customize mailcow's appearance
|
@@ -73,6 +73,81 @@ function customize($_action, $_item, $_data = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_logo'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'upload_success'
|
||||
);
|
||||
break;
|
||||
case 'favicon':
|
||||
if (in_array($_data['favicon']['type'], array('image/png', 'image/x-icon'))) {
|
||||
try {
|
||||
if (file_exists($_data['favicon']['tmp_name']) !== true) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_tmp_missing'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$image = new Imagick($_data['favicon']['tmp_name']);
|
||||
if ($image->valid() !== true) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$available_sizes = array(32, 128, 180, 192, 256);
|
||||
if ($image->getImageWidth() != $image->getImageHeight()) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!in_array($image->getImageWidth(), $available_sizes)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$image->destroy();
|
||||
}
|
||||
catch (ImagickException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'invalid_mime_type'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$redis->Set('FAVICON', 'data:' . $_data['favicon']['type'] . ';base64,' . base64_encode(file_get_contents($_data['favicon']['tmp_name'])));
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_favicon'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
@@ -179,6 +254,34 @@ function customize($_action, $_item, $_data = null) {
|
||||
'msg' => 'ip_check_opt_in_modified'
|
||||
);
|
||||
break;
|
||||
case 'sogo_theme':
|
||||
$_data['primary'] = (isset($_data['primary']) && in_array($_data['primary'], $GLOBALS['SOGO_PALETTES'])) ? $_data['primary'] : 'green';
|
||||
$_data['accent'] = (isset($_data['accent']) && in_array($_data['accent'], $GLOBALS['SOGO_PALETTES'])) ? $_data['accent'] : 'green';
|
||||
$_data['background'] = (isset($_data['background']) && in_array($_data['background'], $GLOBALS['SOGO_PALETTES'])) ? $_data['background'] : 'grey';
|
||||
|
||||
try {
|
||||
$redis->hSet('SOGO_THEME', 'primary', $_data['primary']);
|
||||
$redis->hSet('SOGO_THEME', 'accent', $_data['accent']);
|
||||
$redis->hSet('SOGO_THEME', 'background', $_data['background']);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'customize_enable'));
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_theme'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'sogo_theme_modified'
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
@@ -203,6 +306,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
case 'main_logo':
|
||||
try {
|
||||
if ($redis->del('MAIN_LOGO')) {
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'remove_logo'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
@@ -219,6 +323,51 @@ function customize($_action, $_item, $_data = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'favicon':
|
||||
try {
|
||||
if ($redis->del('FAVICON')) {
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'remove_favicon'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'reset_favicon'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'sogo_theme':
|
||||
try {
|
||||
$redis->hSet('SOGO_THEME', 'primary', 'sogo-blue');
|
||||
$redis->hSet('SOGO_THEME', 'accent', 'sogo-green');
|
||||
$redis->hSet('SOGO_THEME', 'background', 'sogo-grey');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_theme'));
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'customize_disable'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'sogo_theme_removed'
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -251,6 +400,19 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'favicon':
|
||||
try {
|
||||
return $redis->get('FAVICON');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ui_texts':
|
||||
try {
|
||||
$data['title_name'] = ($title_name = $redis->get('TITLE_NAME')) ? $title_name : 'mailcow UI';
|
||||
@@ -295,6 +457,25 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'favicon_specs':
|
||||
try {
|
||||
$image = new Imagick();
|
||||
$img_data = explode('base64,', customize('get', 'favicon'));
|
||||
if ($img_data[1]) {
|
||||
$image->readImageBlob(base64_decode($img_data[1]));
|
||||
return $image->identifyImage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (ImagickException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'imagick_exception'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ip_check':
|
||||
try {
|
||||
$ip_check = ($ip_check = $redis->get('IP_CHECK')) ? $ip_check : 0;
|
||||
@@ -309,6 +490,28 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'sogo_theme':
|
||||
$data = array();
|
||||
try {
|
||||
$data['primary'] = $redis->hGet('SOGO_THEME', 'primary');
|
||||
$data['accent'] = $redis->hGet('SOGO_THEME', 'accent');
|
||||
$data['background'] = $redis->hGet('SOGO_THEME', 'background');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['primary'] = empty($data['primary']) ? 'sogo-blue' : $data['primary'];
|
||||
$data['accent'] = empty($data['accent']) ? 'sogo-green' : $data['accent'];
|
||||
$data['background'] = empty($data['background']) ? 'sogo-grey' : $data['background'];
|
||||
|
||||
return $data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ $globalVariables = [
|
||||
'ui_texts' => $UI_TEXTS,
|
||||
'css_path' => '/cache/'.basename($CSSPath),
|
||||
'logo' => customize('get', 'main_logo'),
|
||||
'favicon' => customize('get', 'favicon'),
|
||||
'available_languages' => $AVAILABLE_LANGUAGES,
|
||||
'lang' => $lang,
|
||||
'skip_sogo' => (getenv('SKIP_SOGO') == 'y'),
|
||||
|
@@ -125,6 +125,14 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi
|
||||
if (isset($_POST["reset_main_logo"])) {
|
||||
customize('delete', 'main_logo');
|
||||
}
|
||||
if (isset($_POST["submit_favicon"])) {
|
||||
if ($_FILES['favicon']['error'] == 0) {
|
||||
customize('add', 'favicon', $_FILES);
|
||||
}
|
||||
}
|
||||
if (isset($_POST["reset_favicon"])) {
|
||||
customize('delete', 'favicon');
|
||||
}
|
||||
// Some actions will not be available via API
|
||||
if (isset($_POST["license_validate_now"])) {
|
||||
license('verify');
|
||||
|
@@ -210,6 +210,30 @@ $FIDO2_USER_PRESENT_FLAG = true;
|
||||
|
||||
$FIDO2_FORMATS = array('apple', 'android-key', 'android-safetynet', 'fido-u2f', 'none', 'packed', 'tpm');
|
||||
|
||||
$SOGO_PALETTES = array(
|
||||
'sogo-green',
|
||||
'sogo-blue',
|
||||
'sogo-grey',
|
||||
'red',
|
||||
'pink',
|
||||
'purple',
|
||||
'deep-purple',
|
||||
'indigo',
|
||||
'blue',
|
||||
'light-blue',
|
||||
'cyan',
|
||||
'teal',
|
||||
'green',
|
||||
'light-green',
|
||||
'lime',
|
||||
'yellow',
|
||||
'amber',
|
||||
'orange',
|
||||
'deep-orange',
|
||||
'brown',
|
||||
'grey',
|
||||
'blue-grey'
|
||||
);
|
||||
|
||||
// Set visible Rspamd maps in mailcow UI, do not change unless you know what you are doing
|
||||
$RSPAMD_MAPS = array(
|
||||
|
@@ -288,18 +288,18 @@ if (isset($_GET['query'])) {
|
||||
case "domain-admin":
|
||||
process_add_return(domain_admin('add', $attr));
|
||||
break;
|
||||
case "sso":
|
||||
switch ($object) {
|
||||
case "domain-admin":
|
||||
$data = domain_admin_sso('issue', $attr);
|
||||
if($data) {
|
||||
echo json_encode($data);
|
||||
exit(0);
|
||||
}
|
||||
process_add_return($data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "sso":
|
||||
switch ($object) {
|
||||
case "domain-admin":
|
||||
$data = domain_admin_sso('issue', $attr);
|
||||
if($data) {
|
||||
echo json_encode($data);
|
||||
exit(0);
|
||||
}
|
||||
process_add_return($data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "admin":
|
||||
process_add_return(admin('add', $attr));
|
||||
break;
|
||||
@@ -1744,6 +1744,9 @@ if (isset($_GET['query'])) {
|
||||
case "rlhash":
|
||||
echo ratelimit('delete', null, implode($items));
|
||||
break;
|
||||
case "sogo_theme":
|
||||
process_delete_return(customize('delete', 'sogo_theme', $items));
|
||||
break;
|
||||
// return no route found if no case is matched
|
||||
default:
|
||||
http_response_code(404);
|
||||
@@ -1938,6 +1941,9 @@ if (isset($_GET['query'])) {
|
||||
case "ip_check":
|
||||
process_edit_return(customize('edit', 'ip_check', $attr));
|
||||
break;
|
||||
case "sogo_theme":
|
||||
process_edit_return(customize('edit', 'sogo_theme', $attr));
|
||||
break;
|
||||
case "self":
|
||||
if ($_SESSION['mailcow_cc_role'] == "domainadmin") {
|
||||
process_edit_return(domain_admin('edit', $attr));
|
||||
|
@@ -145,6 +145,7 @@
|
||||
"ays": "Soll der Vorgang wirklich ausgeführt werden?",
|
||||
"ban_list_info": "Übersicht ausgesperrter Netzwerke: <b>Netzwerk (verbleibende Bannzeit) - [Aktionen]</b>.<br />IPs, die zum Entsperren eingereiht werden, verlassen die Liste aktiver Banns nach wenigen Sekunden.<br />Rote Labels sind Indikatoren für aktive Blacklist-Einträge.",
|
||||
"change_logo": "Logo ändern",
|
||||
"change_favicon": "Favicon ändern",
|
||||
"configuration": "Konfiguration",
|
||||
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
||||
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
||||
@@ -216,6 +217,7 @@
|
||||
"loading": "Bitte warten...",
|
||||
"login_time": "Zeit",
|
||||
"logo_info": "Die hochgeladene Grafik wird für die Navigationsleiste auf eine Höhe von 40px skaliert. Für die Darstellung auf der Login-Maske beträgt die skalierte Breite maximal 250px. Eine frei skalierbare Grafik (etwa SVG) wird empfohlen.",
|
||||
"favicon_info": "Das Bild muss eine PNG- oder ICO-Datei mit den Abmessungen <code>32 x 32</code>, <code>128 x 128</code>, <code>180 x 180</code>, <code>192 x 192</code> oder <code>256 x 256</code> sein. SOGo muss nachdem ändern neugestartet werden.",
|
||||
"lookup_mx": "Ziel mit MX vergleichen (Regex, etwa <code>.*google\\.com</code>, um alle Ziele mit MX *google.com zu routen)",
|
||||
"main_name": "\"mailcow UI\" Name",
|
||||
"merged_vars_hint": "Ausgegraute Reihen wurden aus der Datei <code>vars.(local.)inc.php</code> gelesen und können hier nicht verändert werden.",
|
||||
@@ -306,6 +308,8 @@
|
||||
"sender": "Sender",
|
||||
"service": "Dienst",
|
||||
"service_id": "Service",
|
||||
"sogo_theme": "SOGo Theme",
|
||||
"sogo_theme_info": "SOGo muss nachdem ändern neugestartet werden.",
|
||||
"source": "Quelle",
|
||||
"spamfilter": "Spamfilter",
|
||||
"subject": "Betreff",
|
||||
@@ -1040,6 +1044,7 @@
|
||||
"relayhost_added": "Map-Eintrag %s wurde hinzugefügt",
|
||||
"relayhost_removed": "Map-Eintrag %s wurde entfernt",
|
||||
"reset_main_logo": "Standardgrafik wurde wiederhergestellt",
|
||||
"reset_favicon": "Standard favicon wurde wiederhergestellt",
|
||||
"resource_added": "Ressource %s wurde angelegt",
|
||||
"resource_modified": "Änderungen an Ressource %s wurden gespeichert",
|
||||
"resource_removed": "Ressource %s wurde entfernt",
|
||||
@@ -1052,6 +1057,8 @@
|
||||
"template_modified": "Änderungen am Template %s wurden gespeichert",
|
||||
"template_removed": "Template ID %s wurde gelöscht",
|
||||
"sogo_profile_reset": "ActiveSync-Gerät des Benutzers %s wurde zurückgesetzt",
|
||||
"sogo_theme_modified": "SOGo Theme wurde gespeichert",
|
||||
"sogo_theme_removed": "SOGo Theme wurde entfernt",
|
||||
"tls_policy_map_entry_deleted": "TLS-Richtlinie mit der ID %s wurde gelöscht",
|
||||
"tls_policy_map_entry_saved": "TLS-Richtlinieneintrag \"%s\" wurde gespeichert",
|
||||
"ui_texts": "Änderungen an UI-Texten",
|
||||
|
@@ -147,6 +147,7 @@
|
||||
"ays": "Are you sure you want to proceed?",
|
||||
"ban_list_info": "See a list of banned IPs below: <b>network (remaining ban time) - [actions]</b>.<br />IPs queued to be unbanned will be removed from the active ban list within a few seconds.<br />Red labels indicate active permanent bans by blacklisting.",
|
||||
"change_logo": "Change logo",
|
||||
"change_favicon": "Change favicon",
|
||||
"configuration": "Configuration",
|
||||
"convert_html_to_text": "Convert HTML to plain text",
|
||||
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
||||
@@ -218,6 +219,7 @@
|
||||
"loading": "Please wait...",
|
||||
"login_time": "Login time",
|
||||
"logo_info": "Your image will be scaled to a height of 40px for the top navigation bar and a max. width of 250px for the start page. A scalable graphic is highly recommended.",
|
||||
"favicon_info": "The image has to be a PNG or ICO file in the dimensions <code>32 x 32</code>, <code>128 x 128</code>, <code>180 x 180</code>, <code>192 x 192</code>, or <code>256 x 256</code>. Restart SOGo after changing the favicon",
|
||||
"lookup_mx": "Destination is a regular expression to match against MX name (<code>.*google\\.com</code> to route all mail targeted to a MX ending in google.com over this hop)",
|
||||
"main_name": "\"mailcow UI\" name",
|
||||
"merged_vars_hint": "Greyed out rows were merged from <code>vars.(local.)inc.php</code> and cannot be modified.",
|
||||
@@ -311,6 +313,11 @@
|
||||
"sender": "Sender",
|
||||
"service": "Service",
|
||||
"service_id": "Service ID",
|
||||
"sogo_theme": "SOGo Theme",
|
||||
"sogo_theme_info": "Restart SOGo after changing the theme.",
|
||||
"sogo_theme_primary": "Primary Color:",
|
||||
"sogo_theme_accent": "Accent Color:",
|
||||
"sogo_theme_background": "Background Color:",
|
||||
"source": "Source",
|
||||
"spamfilter": "Spam filter",
|
||||
"subject": "Subject",
|
||||
@@ -1047,6 +1054,7 @@
|
||||
"relayhost_added": "Map entry %s has been added",
|
||||
"relayhost_removed": "Map entry %s has been removed",
|
||||
"reset_main_logo": "Reset to default logo",
|
||||
"reset_favicon": "Reset to default favicon",
|
||||
"resource_added": "Resource %s has been added",
|
||||
"resource_modified": "Changes to mailbox %s have been saved",
|
||||
"resource_removed": "Resource %s has been removed",
|
||||
@@ -1056,6 +1064,8 @@
|
||||
"settings_map_added": "Added settings map entry",
|
||||
"settings_map_removed": "Removed settings map ID %s",
|
||||
"sogo_profile_reset": "SOGo profile for user %s was reset",
|
||||
"sogo_theme_modified": "SOGo Theme has been modified",
|
||||
"sogo_theme_removed": "SOGo Theme has been removed",
|
||||
"template_added": "Added template %s",
|
||||
"template_modified": "Changes to template %s have been saved",
|
||||
"template_removed": "Template ID %s has been deleted",
|
||||
|
@@ -7,31 +7,89 @@
|
||||
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-customize" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_logo }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.logo_info }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<input class="mb-4" type="file" name="main_logo" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml"><br>
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% if logo %}
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="thumbnail">
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-6 d-flex flex-column">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_logo }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.logo_info }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<input class="mb-4" type="file" name="main_logo" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml"><br>
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% if logo %}
|
||||
<div class="thumbnail mt-auto">
|
||||
<img class="img-thumbnail" src="{{ logo }}" alt="mailcow logo">
|
||||
<div class="caption">
|
||||
<div class="caption d-flex flex-wrap mt-2 mb-4">
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info mx-2">{{ logo_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.fileSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<form class="form-inline" role="form" method="post">
|
||||
<p><button name="reset_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary">{{ lang.admin.reset_default }}</button></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 d-flex flex-column">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_favicon }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.favicon_info|raw }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<input class="mb-4" type="file" name="favicon" accept="image/x-icon, image/png"><br>
|
||||
<button name="submit_favicon" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% if favicon %}
|
||||
<div class="thumbnail mt-auto">
|
||||
<img class="img-thumbnail" src="{{ favicon }}" alt="mailcow favicon">
|
||||
<div class="caption d-flex flex-wrap mt-2 mb-4">
|
||||
<span class="badge fs-5 bg-info">{{ favicon_specs.geometry.width }}x{{ favicon_specs.geometry.height }} px</span>
|
||||
<span class="badge fs-5 bg-info mx-2">{{ favicon_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ favicon_specs.fileSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-inline" role="form" method="post">
|
||||
<p><button name="reset_favicon" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary">{{ lang.admin.reset_default }}</button></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not skip_sogo %}
|
||||
<legend style="padding-top:20px" unselectable="on">{{ lang.admin.sogo_theme }}</legend><hr />
|
||||
<form class="form" data-id="sogo_theme" role="form" method="post">
|
||||
<div class="mb-4 row">
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<label class="d-block" for="sogo_primary">{{ lang.admin.sogo_theme_primary }}</label>
|
||||
<select multiple data-width="100%" id="sogo_primary" name="primary" class="selectpicker show-tick" data-max-options="1" data-id="sogo_theme">
|
||||
{% for sogo_palette in sogo_palettes %}
|
||||
<option {% if sogo_palette == sogo_theme.primary %}selected{% endif %} value="{{ sogo_palette }}">{{ sogo_palette }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<label class="d-block" for="sogo_accent">{{ lang.admin.sogo_theme_accent }}</label>
|
||||
<select multiple data-width="100%" id="sogo_accent" name="accent" class="selectpicker show-tick" data-max-options="1" data-id="sogo_theme">
|
||||
{% for sogo_palette in sogo_palettes %}
|
||||
<option {% if sogo_palette == sogo_theme.accent %}selected{% endif %} value="{{ sogo_palette }}">{{ sogo_palette }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<label class="d-block" for="sogo_background">{{ lang.admin.sogo_theme_background }}</label>
|
||||
<select multiple data-width="100%" id="sogo_background" name="background" class="selectpicker show-tick" data-max-options="1" data-id="sogo_theme">
|
||||
{% for sogo_palette in sogo_palettes %}
|
||||
<option {% if sogo_palette == sogo_theme.background %}selected{% endif %} value="{{ sogo_palette }}">{{ sogo_palette }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.admin.sogo_theme_info }}</p>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" type="button" data-action="edit_selected" data-item="sogo-theme" data-id="sogo_theme" data-reload="no" data-api-url='edit/sogo_theme' data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger" type="button" data-action="delete_selected" data-item="sogo-theme" data-id="sogo_theme" data-api-url="delete/sogo_theme"><i class="bi bi-trash"></i> {{ lang.admin.remove }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
<legend style="padding-top:20px" unselectable="on">{{ lang.admin.ip_check }}</legend><hr />
|
||||
<div id="ip_check">
|
||||
|
@@ -23,8 +23,8 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="icon" href="/favicon.png" type="image/png">
|
||||
<link rel="shortcut icon" href="{{ favicon|default('/favicon.png') }}" type="image/png">
|
||||
<link rel="icon" href="{{ favicon|default('/favicon.png') }}" type="image/png">
|
||||
</head>
|
||||
<body>
|
||||
<div class="overlay"></div>
|
||||
|
Reference in New Issue
Block a user