mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-01 13:17:21 +02:00
v3.1.3 init commit
- Fixed #378 - Added wip dark theme - Fixed in code typo - Fixed int conversion bug in some DNS challenge supplier
This commit is contained in:
parent
e79a70b7ac
commit
634e9c9855
@ -230,7 +230,17 @@ func handleCountryBlacklistAdd(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
rule.AddCountryCodeToBlackList(countryCode, comment)
|
||||
//Check if the country code contains comma, if yes, split it
|
||||
if strings.Contains(countryCode, ",") {
|
||||
codes := strings.Split(countryCode, ",")
|
||||
for _, code := range codes {
|
||||
code = strings.TrimSpace(code)
|
||||
rule.AddCountryCodeToBlackList(code, comment)
|
||||
}
|
||||
} else {
|
||||
countryCode = strings.TrimSpace(countryCode)
|
||||
rule.AddCountryCodeToBlackList(countryCode, comment)
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
@ -254,7 +264,17 @@ func handleCountryBlacklistRemove(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
rule.RemoveCountryCodeFromBlackList(countryCode)
|
||||
//Check if the country code contains comma, if yes, split it
|
||||
if strings.Contains(countryCode, ",") {
|
||||
codes := strings.Split(countryCode, ",")
|
||||
for _, code := range codes {
|
||||
code = strings.TrimSpace(code)
|
||||
rule.RemoveCountryCodeFromBlackList(code)
|
||||
}
|
||||
} else {
|
||||
countryCode = strings.TrimSpace(countryCode)
|
||||
rule.RemoveCountryCodeFromBlackList(countryCode)
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
@ -397,7 +417,17 @@ func handleCountryWhitelistAdd(w http.ResponseWriter, r *http.Request) {
|
||||
p := bluemonday.StrictPolicy()
|
||||
comment = p.Sanitize(comment)
|
||||
|
||||
rule.AddCountryCodeToWhitelist(countryCode, comment)
|
||||
//Check if the country code contains comma, if yes, split it
|
||||
if strings.Contains(countryCode, ",") {
|
||||
codes := strings.Split(countryCode, ",")
|
||||
for _, code := range codes {
|
||||
code = strings.TrimSpace(code)
|
||||
rule.AddCountryCodeToWhitelist(code, comment)
|
||||
}
|
||||
} else {
|
||||
countryCode = strings.TrimSpace(countryCode)
|
||||
rule.AddCountryCodeToWhitelist(countryCode, comment)
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
@ -420,7 +450,17 @@ func handleCountryWhitelistRemove(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
rule.RemoveCountryCodeFromWhitelist(countryCode)
|
||||
//Check if the country code contains comma, if yes, split it
|
||||
if strings.Contains(countryCode, ",") {
|
||||
codes := strings.Split(countryCode, ",")
|
||||
for _, code := range codes {
|
||||
code = strings.TrimSpace(code)
|
||||
rule.RemoveCountryCodeFromWhitelist(code)
|
||||
}
|
||||
} else {
|
||||
countryCode = strings.TrimSpace(countryCode)
|
||||
rule.RemoveCountryCodeFromWhitelist(countryCode)
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade
|
||||
|
||||
var (
|
||||
name = "Zoraxy"
|
||||
version = "3.1.2"
|
||||
version = "3.1.3"
|
||||
nodeUUID = "generic" //System uuid, in uuidv4 format
|
||||
development = false //Set this to false to use embedded web fs
|
||||
development = true //Set this to false to use embedded web fs
|
||||
bootTime = time.Now().Unix()
|
||||
|
||||
/*
|
||||
|
@ -3,7 +3,7 @@ package acme
|
||||
/*
|
||||
CA.go
|
||||
|
||||
This script load CA defination from embedded ca.json
|
||||
This script load CA definition from embedded ca.json
|
||||
*/
|
||||
import (
|
||||
_ "embed"
|
||||
@ -13,7 +13,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CA Defination, load from embeded json when startup
|
||||
// CA definition, load from embeded json when startup
|
||||
type CaDef struct {
|
||||
Production map[string]string
|
||||
Test map[string]string
|
||||
|
@ -1,7 +1,7 @@
|
||||
package v308
|
||||
|
||||
/*
|
||||
v307 type definations
|
||||
v307 type definitions
|
||||
|
||||
This file wrap up the self-contained data structure
|
||||
for v3.0.7 structure and allow automatic updates
|
||||
|
@ -1,7 +1,7 @@
|
||||
package v308
|
||||
|
||||
/*
|
||||
v308 type definations
|
||||
v308 type definition
|
||||
|
||||
This file wrap up the self-contained data structure
|
||||
for v3.0.8 structure and allow automatic updates
|
||||
|
@ -1173,7 +1173,7 @@ func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
//Create a Custom Header Defination type
|
||||
//Create a Custom Header Definition type
|
||||
var rewriteDirection rewrite.HeaderDirection
|
||||
if direction == "toOrigin" {
|
||||
rewriteDirection = rewrite.HeaderDirection_ZoraxyToUpstream
|
||||
|
@ -841,6 +841,25 @@
|
||||
function initBannedCountryList(){
|
||||
$.get("/api/blacklist/list?type=country&id=" + currentEditingAccessRule, function(data) {
|
||||
let bannedListHtml = '';
|
||||
|
||||
//Check if the country code list contains all eu countries. If yes, replace it with "EU"
|
||||
let allEu = true;
|
||||
let euCountries = getEUCCs();
|
||||
for (var i = 0; i < euCountries.length; i++){
|
||||
if (!data.includes(euCountries[i])){
|
||||
allEu = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allEu){
|
||||
//Remove EU countries from the list and replace it with EU
|
||||
data = data.filter(function(value, index, arr){
|
||||
return !euCountries.includes(value);
|
||||
});
|
||||
data.push("eu");
|
||||
}
|
||||
|
||||
data.forEach((countryCode) => {
|
||||
bannedListHtml += `
|
||||
<tr>
|
||||
@ -919,18 +938,48 @@
|
||||
//Whitelist country table
|
||||
function initWhitelistCountryList(){
|
||||
$.get("/api/whitelist/list?type=country&id=" + currentEditingAccessRule, function(data) {
|
||||
let bannedListHtml = '';
|
||||
let whiteListHTML = '';
|
||||
|
||||
//Check if the country code list contains all eu countries. If yes, replace it with "EU"
|
||||
let allEu = true;
|
||||
let euCountries = getEUCCs();
|
||||
let countryCodesIndata = data.map(function(item){
|
||||
//data[n].CC is the country code
|
||||
return item.CC;
|
||||
});
|
||||
for (var i = 0; i < euCountries.length; i++){
|
||||
if (!countryCodesIndata.includes(euCountries[i])){
|
||||
allEu = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allEu){
|
||||
//Remove EU countries from the list and replace it with EU
|
||||
data = data.filter(function(value, index, arr){
|
||||
return !euCountries.includes(value.CC);
|
||||
});
|
||||
data.push({
|
||||
CC: "eu"
|
||||
});
|
||||
}
|
||||
|
||||
data.forEach((countryWhitelistEntry) => {
|
||||
let countryCode = countryWhitelistEntry.CC;
|
||||
bannedListHtml += `
|
||||
whiteListHTML += `
|
||||
<tr>
|
||||
<td><i class="${countryCode} flag"></i> ${getCountryName(countryCode)} (${countryCode.toUpperCase()})</td>
|
||||
<td><button class="ui red basic mini icon button" onclick="removeFromWhiteList('${countryCode}')"><i class="trash icon"></i></button></td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
$('#whitelistCountryList').html(bannedListHtml);
|
||||
filterCountries(data, "#countrySelectorWhitelist .menu .item");
|
||||
$('#whitelistCountryList').html(whiteListHTML);
|
||||
|
||||
//Map the data.CC to the country code
|
||||
let countryCodes = data.map(function(item){
|
||||
return item.CC;
|
||||
});
|
||||
filterCountries(countryCodes, "#countrySelectorWhitelist .menu .item");
|
||||
if (data.length === 0) {
|
||||
$('#whitelistCountryList').append(`
|
||||
<tr>
|
||||
@ -1016,6 +1065,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
function getEUCCs(){
|
||||
return ["at","be","bg","cy","cz","de","dk","ee","es","fi","fr","gr","hr","hu","ie","it","lt","lu","lv","mt","nl","pl","pt","se","si","sk"];
|
||||
}
|
||||
|
||||
function addCountryToBlacklist() {
|
||||
var countryCode = $("#countrySelector").dropdown("get value").toLowerCase();
|
||||
let ccs = [countryCode];
|
||||
@ -1025,48 +1078,50 @@
|
||||
ccs = countryCode.split(",");
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
for(var i = 0; i < ccs.length; i++){
|
||||
let thisCountryCode = ccs[i];
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/blacklist/country/add",
|
||||
method: "POST",
|
||||
data: { cc: thisCountryCode, id: currentEditingAccessRule},
|
||||
success: function(response) {
|
||||
if (response.error != undefined){
|
||||
msgbox(response.error, false);
|
||||
}
|
||||
|
||||
if (counter == (ccs.length - 1)){
|
||||
//Last item
|
||||
setTimeout(function(){
|
||||
initBannedCountryList();
|
||||
if (ccs.length == 1){
|
||||
//Single country
|
||||
msgbox(`Added ${getCountryName(ccs[0])} to blacklist`);
|
||||
}else{
|
||||
msgbox(ccs.length + " countries added to blacklist");
|
||||
}
|
||||
|
||||
}, (ccs.length==1)?0:100);
|
||||
}
|
||||
counter++;
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// handle error response
|
||||
}
|
||||
//If the ccs includes "eu", remove the "eu" and add all eu country code to the list
|
||||
if (ccs.includes("eu")){
|
||||
ccs = ccs.concat(getEUCCs());
|
||||
ccs = ccs.filter(function(item){
|
||||
return item != "eu";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
let counter = ccs.length;
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/blacklist/country/add",
|
||||
method: "POST",
|
||||
data: { cc: ccs.join(","), id: currentEditingAccessRule},
|
||||
success: function(response) {
|
||||
if (response.error != undefined){
|
||||
msgbox(response.error, false);
|
||||
}
|
||||
initBannedCountryList();
|
||||
if (ccs.length == 1){
|
||||
//Single country
|
||||
msgbox(`Added ${getCountryName(ccs[0])} to blacklist`);
|
||||
}else{
|
||||
msgbox(ccs.length + " countries added to blacklist");
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// handle error response
|
||||
}
|
||||
});
|
||||
$('#countrySelector').dropdown('clear');
|
||||
|
||||
}
|
||||
|
||||
function removeFromBannedList(countryCode){
|
||||
countryCode = countryCode.toLowerCase();
|
||||
let countryName = getCountryName(countryCode);
|
||||
if (countryCode == "eu"){
|
||||
let euCountries = getEUCCs();
|
||||
countryCode = euCountries.join(",");
|
||||
countryName = "European Union";
|
||||
}else{
|
||||
countryCode = countryCode.toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
$.cjax({
|
||||
url: "/api/blacklist/country/remove",
|
||||
method: "POST",
|
||||
@ -1162,44 +1217,53 @@
|
||||
//Usually just a few countries a for loop will get the job done
|
||||
ccs = countryCode.split(",");
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
for(var i = 0; i < ccs.length; i++){
|
||||
let thisCountryCode = ccs[i];
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/whitelist/country/add",
|
||||
data: { cc: thisCountryCode , id: currentEditingAccessRule},
|
||||
success: function(response) {
|
||||
if (response.error != undefined){
|
||||
msgbox(response.error, false);
|
||||
}
|
||||
|
||||
if (counter == (ccs.length - 1)){
|
||||
setTimeout(function(){
|
||||
initWhitelistCountryList();
|
||||
if (ccs.length == 1){
|
||||
//Single country
|
||||
msgbox(`Added ${getCountryName(ccs[0])} to whitelist`);
|
||||
}else{
|
||||
msgbox(ccs.length + " countries added to whitelist");
|
||||
}
|
||||
}, (ccs.length==1)?0:100);
|
||||
}
|
||||
counter++;
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// handle error response
|
||||
}
|
||||
//If the ccs includes "eu", remove the "eu" and add all eu country code to the list
|
||||
if (ccs.includes("eu")){
|
||||
ccs = ccs.filter(function(item){
|
||||
return item != "eu";
|
||||
});
|
||||
ccs = ccs.concat(getEUCCs());
|
||||
}
|
||||
|
||||
let counter = ccs.length;
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/whitelist/country/add",
|
||||
data: { cc: ccs.join(",") , id: currentEditingAccessRule},
|
||||
success: function(response) {
|
||||
if (response.error != undefined){
|
||||
msgbox(response.error, false);
|
||||
}
|
||||
|
||||
initWhitelistCountryList();
|
||||
if (ccs.length == 1){
|
||||
//Single country
|
||||
msgbox(`Added ${getCountryName(ccs[0])} to whitelist`);
|
||||
}else{
|
||||
msgbox(ccs.length + " countries added to whitelist");
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// handle error response
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('#countrySelectorWhitelist').dropdown('clear');
|
||||
}
|
||||
|
||||
function removeFromWhiteList(countryCode){
|
||||
if (confirm("Confirm removing " + getCountryName(countryCode) + " from whitelist?")){
|
||||
//Remove from whitelist, accepts a country code or "eu" for all EU countries
|
||||
function removeFromWhiteList(countryCode, skipConfirm = true){
|
||||
let countryName = getCountryName(countryCode);
|
||||
if (countryCode == "eu"){
|
||||
let euCountries = getEUCCs();
|
||||
countryCode = euCountries.join(",");
|
||||
countryName = "European Union";
|
||||
}else{
|
||||
countryCode = countryCode.toLowerCase();
|
||||
}
|
||||
if (skipConfirm || confirm("Confirm removing " + getCountryName(countryCode) + " from whitelist?")){
|
||||
$.cjax({
|
||||
url: "/api/whitelist/country/remove",
|
||||
method: "POST",
|
||||
@ -1208,6 +1272,7 @@
|
||||
if (response.error != undefined){
|
||||
msgbox(response.error, false);
|
||||
}
|
||||
msgbox(countryName + " removed from whitelist");
|
||||
initWhitelistCountryList();
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
@ -1276,19 +1341,27 @@
|
||||
/*
|
||||
Common Utilities
|
||||
*/
|
||||
function filterCountries(codesToShow, selector="#countrySelector .menu .item") {
|
||||
function filterCountries(alreadySelectedCCs, selector="#countrySelector .menu .item") {
|
||||
// get all items in the dropdown
|
||||
const items = document.querySelectorAll(selector);
|
||||
const euCountries = getEUCCs();
|
||||
//Replce "eu" in alreadySelectedCCs with all EU countries
|
||||
if (alreadySelectedCCs.includes("eu")){
|
||||
alreadySelectedCCs = alreadySelectedCCs.filter(function(item){
|
||||
return item != "eu";
|
||||
});
|
||||
alreadySelectedCCs = alreadySelectedCCs.concat(euCountries);
|
||||
}
|
||||
|
||||
// loop through all items
|
||||
items.forEach(item => {
|
||||
// get the value of the item (i.e. the country code)
|
||||
const code = item.dataset.value;
|
||||
// if the code is in the array of codes to show, show the item
|
||||
if (codesToShow.includes(code)) {
|
||||
if (alreadySelectedCCs.includes(code)) {
|
||||
//This country code already selected. Hide it
|
||||
item.style.display = 'none';
|
||||
}
|
||||
// otherwise, hide the item
|
||||
else {
|
||||
} else {
|
||||
// otherwise, show the item
|
||||
item.style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
@ -30,7 +30,7 @@
|
||||
<i class="ui green checkmark icon"></i> Redirection Rule Deleted
|
||||
</div>
|
||||
<!-- Options -->
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div class="ui accordion advanceSettings">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
|
@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Advance configs -->
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div id="advanceProxyRules" class="ui fluid accordion">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
|
@ -94,7 +94,7 @@
|
||||
<label>Force redirect HTTP request to HTTPS</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div class="ui accordion advanceSettings">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
@ -579,7 +579,7 @@
|
||||
let timestamps = [];
|
||||
|
||||
for(var i = 0; i < dataCount; i++){
|
||||
timestamps.push(parseInt(Date.now() / 1000) + i);
|
||||
timestamps.push(new Date(Date.now() + i * 1000).toLocaleString().replace(',', ''));
|
||||
}
|
||||
|
||||
function fetchData() {
|
||||
@ -600,10 +600,8 @@
|
||||
txValues.shift();
|
||||
}
|
||||
|
||||
|
||||
timestamps.push(parseInt(Date.now() / 1000));
|
||||
timestamps.push(new Date(Date.now()).toLocaleString().replace(',', ''));
|
||||
timestamps.shift();
|
||||
|
||||
updateChart();
|
||||
}
|
||||
})
|
||||
|
@ -69,7 +69,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Advance configs -->
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div id="advanceProxyRules" class="ui fluid accordion">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
|
330
src/web/darktheme.css
Normal file
330
src/web/darktheme.css
Normal file
@ -0,0 +1,330 @@
|
||||
/*
|
||||
Darktheme CSS
|
||||
|
||||
This file contains the CSS for the dark theme.
|
||||
This will override the default CSS (white theme) for semantic UI
|
||||
*/
|
||||
|
||||
body.darkTheme {
|
||||
background-color: var(--theme_bg);
|
||||
color: var(--text_color);
|
||||
}
|
||||
|
||||
body.darkTheme h1,
|
||||
body.darkTheme h2,
|
||||
body.darkTheme h3,
|
||||
body.darkTheme h4,
|
||||
body.darkTheme h5,
|
||||
body.darkTheme h6,
|
||||
body.darkTheme a {
|
||||
color: var(--text_color);
|
||||
}
|
||||
|
||||
body.darkTheme .ui.header {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme p,
|
||||
body.darkTheme span{
|
||||
color: var(--text_color_secondary);
|
||||
}
|
||||
|
||||
body.darkTheme .ui.secondary.menu .dropdown.item:hover,
|
||||
body.darkTheme .ui.secondary.menu .link.item:hover,
|
||||
body.darkTheme .ui.secondary.menu a.item:hover {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.white.icon.button {
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.white.icon.button:hover {
|
||||
border: none !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.white.icon.button:disabled {
|
||||
border: none !important;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.buttons .button i.icon {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.button:not(.red) {
|
||||
color: #ffffff !important;
|
||||
border: 1px solid var(--button_border_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.button:not(.red):hover {
|
||||
border: 1px solid var(--button_border_color) !important;
|
||||
background-color: var(--theme_bg) !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.button.red:hover {
|
||||
background-color: #380a0a !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.button:disabled {
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.button:focus,
|
||||
body.darkTheme .ui.basic.buttons .button:focus {
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
|
||||
body.darkTheme .ui.table thead th,
|
||||
body.darkTheme .ui.table tbody td,
|
||||
body.darkTheme .ui.table tfoot td {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.input input,
|
||||
body.darkTheme .ui.input input::placeholder,
|
||||
body.darkTheme .ui.input input:focus,
|
||||
body.darkTheme .ui.input input:active {
|
||||
color: #ffffff !important;
|
||||
border-color: #ffffff !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.input input {
|
||||
background-color: var(--theme_bg_active) !important;
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.input input:focus,
|
||||
body.darkTheme .ui.input input:active {
|
||||
border-color: var(--theme_highlight) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.input input::placeholder {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.label,
|
||||
body.darkTheme .ui.label .detail,
|
||||
body.darkTheme .ui.label .icon {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
body.darkTheme .advanceoptions .title {
|
||||
color: var(--text_color_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.toggle.checkbox input ~ .box,
|
||||
body.darkTheme .ui.toggle.checkbox input ~ label,
|
||||
body.darkTheme .ui.toggle.checkbox input ~ label:focus {
|
||||
color: var(--text_color_secondary) !important;
|
||||
}
|
||||
|
||||
|
||||
body.darkTheme .ui.toggle.checkbox input ~ label::before{
|
||||
background-color: var(--theme_bg_secondary) !important;
|
||||
}
|
||||
body.darkTheme .ui.toggle.checkbox input:checked ~ label::before{
|
||||
background-color: var(--theme_highlight) !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
body.darkTheme .ui.segment:not(.basic) {
|
||||
background-color: var(--theme_bg) !important;
|
||||
color: var(--text_color) !important;
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
body.darkTheme .sub.header {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.radio.defaultsite.checkbox label {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.radio.defaultsite.checkbox label small {
|
||||
color: var(--text_color_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.form .field input,
|
||||
body.darkTheme .ui.form .field input::placeholder,
|
||||
body.darkTheme .ui.form .field input:focus,
|
||||
body.darkTheme .ui.form .field input:active {
|
||||
color: var(--text_color) !important;
|
||||
border-color: 1px solid transparent !important;
|
||||
background-color: var(--theme_bg_active) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.form .field input::placeholder {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.form .field label,
|
||||
body.darkTheme .ui.form .field .ui.checkbox input:checked ~ label {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.label {
|
||||
background-color: var(--theme_bg_secondary) !important;
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
/*
|
||||
HTTP Proxy Table
|
||||
*/
|
||||
body.darkTheme .ui.table{
|
||||
background-color: transparent !important;
|
||||
}
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table thead th,
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td,
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tfoot td {
|
||||
background-color: var(--theme_bg) !important;
|
||||
color: var(--text_color) !important;
|
||||
border-color: var(--divider_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table thead th {
|
||||
background-color: var(--theme_bg_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody tr:hover {
|
||||
background-color: var(--theme_bg_hover) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td a {
|
||||
color: var(--link_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td a:hover {
|
||||
color: var(--link_hover_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td small {
|
||||
color: var(--text_color_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.toggle.checkbox input ~ .box,
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.toggle.checkbox input ~ label,
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.toggle.checkbox input ~ label:focus {
|
||||
color: var(--text_color_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.toggle.checkbox input ~ label::before {
|
||||
background-color: var(--theme_bg_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.toggle.checkbox input:checked ~ label::before {
|
||||
background-color: var(--theme_highlight) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.circular.mini.basic.icon.button {
|
||||
color: var(--button_color) !important;
|
||||
border: 1px solid var(--button_border_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.circular.mini.basic.icon.button:hover {
|
||||
background-color: var(--button_hover_bg) !important;
|
||||
color: var(--button_hover_color) !important;
|
||||
border: 1px solid var(--button_border_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.circular.mini.red.basic.icon.button {
|
||||
color: var(--button_red_color) !important;
|
||||
border: 1px solid var(--button_red_border_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.celled.sortable.unstackable.compact.table tbody td .ui.circular.mini.red.basic.icon.button:hover {
|
||||
background-color: #380a0a !important;
|
||||
color: var(--button_red_hover_color) !important;
|
||||
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.small.icon.circular.button {
|
||||
color: var(--button_color) !important;
|
||||
border: 1px solid var(--button_border_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.small.icon.circular.button:hover {
|
||||
background-color: var(--button_hover_bg) !important;
|
||||
color: var(--button_hover_color) !important;
|
||||
border: 1px solid var(--button_border_color) !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.checkbox input ~ .box,
|
||||
body.darkTheme .ui.checkbox input ~ label,
|
||||
body.darkTheme .ui.checkbox input ~ label:focus {
|
||||
color: var(--text_color_secondary) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.basic.advance.segment {
|
||||
background-color: var(--theme_bg) !important;
|
||||
color: var(--text_color) !important;
|
||||
border: 1px solid var(--divider_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.endpointAdvanceConfig.accordion .title {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
/*
|
||||
Virtual Directorie Table
|
||||
|
||||
*/
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown {
|
||||
background-color: var(--theme_bg) !important;
|
||||
color: var(--text_color) !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .menu {
|
||||
background-color: var(--theme_bg) !important;
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .menu .item {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.selection.dropdown .menu > .item {
|
||||
border-top: 1px solid var(--divider_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.selection.active.dropdown .menu {
|
||||
border-color: var(--divider_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .menu .item:hover {
|
||||
background-color: var(--theme_bg_hover) !important;
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .menu .item.active.selected {
|
||||
background-color: var(--theme_highlight) !important;
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .search {
|
||||
background-color: var(--theme_bg) !important;
|
||||
color: var(--text_color) !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .text {
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
|
||||
body.darkTheme .ui.fluid.search.selection.dropdown .dropdown.icon {
|
||||
color: var(--text_color) !important;
|
||||
}
|
@ -16,8 +16,10 @@
|
||||
<script src="script/chart.js"></script>
|
||||
<script src="script/utils.js"></script>
|
||||
<link rel="stylesheet" href="main.css">
|
||||
<link rel="stylesheet" href="darktheme.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="script/darktheme.js"></script>
|
||||
<div class="menubar">
|
||||
<div class="item">
|
||||
<img class="logo" src="img/logo.svg">
|
||||
@ -29,9 +31,9 @@
|
||||
<div class="ui right floated buttons" style="padding-top: 2px; padding-right: 0.4em;">
|
||||
<button class="ui basic white icon button" onclick="logout();"><i class="sign-out icon"></i></button>
|
||||
</div>
|
||||
<!-- <div class="ui right floated buttons" style="padding-top: 2px;">
|
||||
<div class="ui right floated buttons" style="padding-top: 2px; margin-right: 0.4em;">
|
||||
<button id="themeColorButton" class="ui icon button" onclick="toggleTheme();"><i class="sun icon"></i></button>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper">
|
||||
<div class="toolbar">
|
||||
@ -269,11 +271,9 @@
|
||||
|
||||
function toggleTheme(){
|
||||
if ($("body").hasClass("darkTheme")){
|
||||
$("body").removeClass("darkTheme")
|
||||
$("#themeColorButton").html(`<i class="ui moon icon"></i>`);
|
||||
setDarkTheme(false);
|
||||
}else{
|
||||
$("body").addClass("darkTheme");
|
||||
$("#themeColorButton").html(`<i class="ui sun icon"></i>`);
|
||||
setDarkTheme(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,10 @@
|
||||
index.html style overwrite
|
||||
*/
|
||||
:root{
|
||||
--theme_background: linear-gradient(60deg, rgb(84, 58, 183) 0%, rgb(0, 172, 193) 100%);
|
||||
--theme_background_inverted: linear-gradient(215deg, rgba(38,60,71,1) 13%, rgba(2,3,42,1) 84%);
|
||||
--theme_green: linear-gradient(270deg, #27e7ff, #00ca52);
|
||||
--theme_red: linear-gradient(203deg, rgba(250,172,38,1) 17%, rgba(202,0,37,1) 78%);
|
||||
|
||||
}
|
||||
|
||||
/* Theme Color Definations */
|
||||
/* Theme Color Definition */
|
||||
body:not(.darkTheme){
|
||||
--theme_bg: #f6f6f6;
|
||||
--theme_bg_primary: #ffffff;
|
||||
@ -16,7 +13,7 @@ body:not(.darkTheme){
|
||||
--theme_bg_active: #ececec;
|
||||
--theme_highlight: #a9d1f3;
|
||||
--theme_bg_inverted: #27292d;
|
||||
--theme_advance: #f8f8f9;
|
||||
--theme_advance: #f7f7f7;
|
||||
--item_color: #5e5d5d;
|
||||
--item_color_select: rgba(0,0,0,.87);
|
||||
--text_color: #414141;
|
||||
@ -25,25 +22,35 @@ body:not(.darkTheme){
|
||||
--text_color_inverted: #fcfcfc;
|
||||
--button_text_color: #878787;
|
||||
--button_border_color: #dedede;
|
||||
|
||||
--theme_background: linear-gradient(60deg, rgb(84, 58, 183) 0%, rgb(0, 172, 193) 100%);
|
||||
--theme_background_inverted: linear-gradient(215deg, rgba(38,60,71,1) 13%, rgba(2,3,42,1) 84%);
|
||||
--theme_green: linear-gradient(270deg, #27e7ff, #00ca52);
|
||||
--theme_red: linear-gradient(203deg, rgba(250,172,38,1) 17%, rgba(202,0,37,1) 78%);
|
||||
}
|
||||
|
||||
body.darkTheme{
|
||||
--theme_bg: #27292d;
|
||||
--theme_bg_primary: #3d3f47;
|
||||
--theme_bg_secondary: #373a42;
|
||||
--theme_highlight: #6682c4;
|
||||
--theme_bg_active: #292929;
|
||||
--theme_bg: #000000;
|
||||
--theme_bg_primary: #141414;
|
||||
--theme_bg_secondary:#230046;
|
||||
--theme_highlight: #320064;
|
||||
--theme_bg_active: #020101;
|
||||
--theme_bg_inverted: #f8f8f9;
|
||||
--theme_advance: #333333;
|
||||
--theme_advance: #000000;
|
||||
--item_color: #cacaca;
|
||||
--text_color: #fcfcfc;
|
||||
--text_color_secondary: #dfdfdf;
|
||||
--text_color: #eef1f3;
|
||||
--text_color_secondary: #b5c0c7;
|
||||
--input_color: black;
|
||||
--divider_color: #3b3b3b;
|
||||
--divider_color: #282828;
|
||||
--item_color_select: rgba(255, 255, 255, 0.87);
|
||||
--text_color_inverted: #414141;
|
||||
--button_text_color: #e9e9e9;
|
||||
--button_border_color: #646464;
|
||||
|
||||
--theme_background: linear-gradient(214deg, rgba(3,1,70,1) 17%, rgba(60,1,80,1) 78%);
|
||||
--theme_background_inverted: linear-gradient(215deg, rgba(38,60,71,1) 13%, rgba(2,3,42,1) 84%);
|
||||
--theme_green: linear-gradient(214deg, rgba(25,128,94,1) 17%, rgba(62,76,111,1) 78%);
|
||||
--theme_red: linear-gradient(203deg, rgba(250,172,38,1) 17%, rgba(202,0,37,1) 78%);
|
||||
}
|
||||
|
||||
/* Theme Toggle CSS */
|
||||
@ -368,7 +375,7 @@ body{
|
||||
}
|
||||
|
||||
.basic.segment.advanceoptions{
|
||||
background-color: #f7f7f7;
|
||||
background-color: var(--theme_advance);
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
|
51
src/web/script/darktheme.js
Normal file
51
src/web/script/darktheme.js
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
Dark Theme Toggle Manager
|
||||
|
||||
This script is used to manage the dark theme toggle button in the header of the website.
|
||||
It will change the theme of the website to dark mode when the toggle is clicked and back to light mode when clicked again.
|
||||
|
||||
Must be included just after the start of body tag in the HTML file.
|
||||
*/
|
||||
|
||||
function _whiteThemeHandleApplyChange(){
|
||||
$(".menubar .logo").attr("src", "img/logo.svg");
|
||||
}
|
||||
|
||||
function _darkThemeHandleApplyChange(){
|
||||
$(".menubar .logo").attr("src", "img/logo_white.svg");
|
||||
}
|
||||
|
||||
|
||||
//Check if the theme is dark, must be done before the body is loaded to prevent flickering
|
||||
function setDarkTheme(isDarkTheme = false){
|
||||
if (isDarkTheme){
|
||||
$("body").addClass("darkTheme");
|
||||
$("#themeColorButton").html(`<i class="ui sun icon"></i>`);
|
||||
localStorage.setItem("theme", "dark");
|
||||
|
||||
//Check if the page is still loading, if not change the logo
|
||||
if (document.readyState == "complete"){
|
||||
_darkThemeHandleApplyChange();
|
||||
}else{
|
||||
//Wait for the page to load and then change the logo
|
||||
$(document).ready(function(){
|
||||
_darkThemeHandleApplyChange();
|
||||
});
|
||||
}
|
||||
}else{
|
||||
$("body").removeClass("darkTheme")
|
||||
$("#themeColorButton").html(`<i class="ui moon icon"></i>`);
|
||||
localStorage.setItem("theme", "light");
|
||||
//By default the page is white theme. So no need to change the logo if page is still loading
|
||||
if (document.readyState == "complete"){
|
||||
//Switching back to light theme
|
||||
_whiteThemeHandleApplyChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (localStorage.getItem("theme") == "dark"){
|
||||
setDarkTheme(true);
|
||||
}else{
|
||||
setDarkTheme(false);
|
||||
}
|
@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<small>If you don't want to share your private email address, you can also fill in an email address that point to a mailbox not exists on your domain.</small>
|
||||
</div>
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div class="ui accordion advanceSettings">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
@ -437,11 +437,15 @@
|
||||
let optionalFieldsHTML = "";
|
||||
for (const [key, datatype] of Object.entries(data)) {
|
||||
if (datatype == "int"){
|
||||
$("#dnsProviderAPIFields").append(`<div class="ui fluid labeled dnsConfigField input" key="${key}" style="margin-top: 0.2em;">
|
||||
let defaultValue = 10;
|
||||
if (key == "HTTPTimeout"){
|
||||
defaultValue = 300;
|
||||
}
|
||||
$("#dnsProviderAPIFields").append(`<div class="ui fluid labeled dnsConfigField input typeint" key="${key}" style="margin-top: 0.2em;">
|
||||
<div class="ui basic blue label" style="font-weight: 300;">
|
||||
${key}
|
||||
</div>
|
||||
<input type="number" value="300">
|
||||
<input type="number" value="${defaultValue}">
|
||||
</div>`);
|
||||
}else if (datatype == "bool"){
|
||||
booleanFieldsHTML += (`<div class="ui checkbox dnsConfigField" key="${key}" style="margin-top: 1em !important; padding-left: 0.4em;">
|
||||
@ -600,8 +604,12 @@
|
||||
//Boolean option
|
||||
let checked = $(this).find("input")[0].checked;
|
||||
dnsCredentials[thisKey] = checked;
|
||||
}else if ($(this).hasClass("typeint")){
|
||||
//Int options
|
||||
let value = $(this).find("input").val();
|
||||
dnsCredentials[thisKey] = parseInt(value);
|
||||
}else{
|
||||
//String or int options
|
||||
//String options
|
||||
let value = $(this).find("input").val().trim();
|
||||
dnsCredentials[thisKey] = value;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div class="ui fluid accordion">
|
||||
<div class="title">
|
||||
<i class="dropdown icon" tabindex="0"><div class="menu" tabindex="-1"></div></i>
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
Color definations
|
||||
Color definition
|
||||
*/
|
||||
:root{
|
||||
--dark_theme_toggle: #333333;
|
||||
|
Loading…
x
Reference in New Issue
Block a user