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:
Toby Chui 2024-11-08 22:24:07 +08:00
parent e79a70b7ac
commit 634e9c9855
18 changed files with 629 additions and 122 deletions

View File

@ -230,7 +230,17 @@ func handleCountryBlacklistAdd(w http.ResponseWriter, r *http.Request) {
return 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) utils.SendOK(w)
} }
@ -254,7 +264,17 @@ func handleCountryBlacklistRemove(w http.ResponseWriter, r *http.Request) {
return 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) utils.SendOK(w)
} }
@ -397,7 +417,17 @@ func handleCountryWhitelistAdd(w http.ResponseWriter, r *http.Request) {
p := bluemonday.StrictPolicy() p := bluemonday.StrictPolicy()
comment = p.Sanitize(comment) 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) utils.SendOK(w)
} }
@ -420,7 +450,17 @@ func handleCountryWhitelistRemove(w http.ResponseWriter, r *http.Request) {
return 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) utils.SendOK(w)
} }

View File

@ -60,9 +60,9 @@ var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade
var ( var (
name = "Zoraxy" name = "Zoraxy"
version = "3.1.2" version = "3.1.3"
nodeUUID = "generic" //System uuid, in uuidv4 format 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() bootTime = time.Now().Unix()
/* /*

View File

@ -3,7 +3,7 @@ package acme
/* /*
CA.go CA.go
This script load CA defination from embedded ca.json This script load CA definition from embedded ca.json
*/ */
import ( import (
_ "embed" _ "embed"
@ -13,7 +13,7 @@ import (
"strings" "strings"
) )
// CA Defination, load from embeded json when startup // CA definition, load from embeded json when startup
type CaDef struct { type CaDef struct {
Production map[string]string Production map[string]string
Test map[string]string Test map[string]string

View File

@ -1,7 +1,7 @@
package v308 package v308
/* /*
v307 type definations v307 type definitions
This file wrap up the self-contained data structure This file wrap up the self-contained data structure
for v3.0.7 structure and allow automatic updates for v3.0.7 structure and allow automatic updates

View File

@ -1,7 +1,7 @@
package v308 package v308
/* /*
v308 type definations v308 type definition
This file wrap up the self-contained data structure This file wrap up the self-contained data structure
for v3.0.8 structure and allow automatic updates for v3.0.8 structure and allow automatic updates

View File

@ -1173,7 +1173,7 @@ func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) {
return return
} }
//Create a Custom Header Defination type //Create a Custom Header Definition type
var rewriteDirection rewrite.HeaderDirection var rewriteDirection rewrite.HeaderDirection
if direction == "toOrigin" { if direction == "toOrigin" {
rewriteDirection = rewrite.HeaderDirection_ZoraxyToUpstream rewriteDirection = rewrite.HeaderDirection_ZoraxyToUpstream

View File

@ -841,6 +841,25 @@
function initBannedCountryList(){ function initBannedCountryList(){
$.get("/api/blacklist/list?type=country&id=" + currentEditingAccessRule, function(data) { $.get("/api/blacklist/list?type=country&id=" + currentEditingAccessRule, function(data) {
let bannedListHtml = ''; 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) => { data.forEach((countryCode) => {
bannedListHtml += ` bannedListHtml += `
<tr> <tr>
@ -919,18 +938,48 @@
//Whitelist country table //Whitelist country table
function initWhitelistCountryList(){ function initWhitelistCountryList(){
$.get("/api/whitelist/list?type=country&id=" + currentEditingAccessRule, function(data) { $.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) => { data.forEach((countryWhitelistEntry) => {
let countryCode = countryWhitelistEntry.CC; let countryCode = countryWhitelistEntry.CC;
bannedListHtml += ` whiteListHTML += `
<tr> <tr>
<td><i class="${countryCode} flag"></i> ${getCountryName(countryCode)} (${countryCode.toUpperCase()})</td> <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> <td><button class="ui red basic mini icon button" onclick="removeFromWhiteList('${countryCode}')"><i class="trash icon"></i></button></td>
</tr> </tr>
`; `;
}); });
$('#whitelistCountryList').html(bannedListHtml); $('#whitelistCountryList').html(whiteListHTML);
filterCountries(data, "#countrySelectorWhitelist .menu .item");
//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) { if (data.length === 0) {
$('#whitelistCountryList').append(` $('#whitelistCountryList').append(`
<tr> <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() { function addCountryToBlacklist() {
var countryCode = $("#countrySelector").dropdown("get value").toLowerCase(); var countryCode = $("#countrySelector").dropdown("get value").toLowerCase();
let ccs = [countryCode]; let ccs = [countryCode];
@ -1025,48 +1078,50 @@
ccs = countryCode.split(","); ccs = countryCode.split(",");
} }
let counter = 0; //If the ccs includes "eu", remove the "eu" and add all eu country code to the list
for(var i = 0; i < ccs.length; i++){ if (ccs.includes("eu")){
let thisCountryCode = ccs[i]; ccs = ccs.concat(getEUCCs());
$.cjax({ ccs = ccs.filter(function(item){
type: "POST", return item != "eu";
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
}
}); });
} }
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'); $('#countrySelector').dropdown('clear');
} }
function removeFromBannedList(countryCode){ function removeFromBannedList(countryCode){
countryCode = countryCode.toLowerCase();
let countryName = getCountryName(countryCode); let countryName = getCountryName(countryCode);
if (countryCode == "eu"){
let euCountries = getEUCCs();
countryCode = euCountries.join(",");
countryName = "European Union";
}else{
countryCode = countryCode.toLowerCase();
}
$.cjax({ $.cjax({
url: "/api/blacklist/country/remove", url: "/api/blacklist/country/remove",
method: "POST", method: "POST",
@ -1162,44 +1217,53 @@
//Usually just a few countries a for loop will get the job done //Usually just a few countries a for loop will get the job done
ccs = countryCode.split(","); 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)){ //If the ccs includes "eu", remove the "eu" and add all eu country code to the list
setTimeout(function(){ if (ccs.includes("eu")){
initWhitelistCountryList(); ccs = ccs.filter(function(item){
if (ccs.length == 1){ return item != "eu";
//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
}
}); });
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'); $('#countrySelectorWhitelist').dropdown('clear');
} }
function removeFromWhiteList(countryCode){ //Remove from whitelist, accepts a country code or "eu" for all EU countries
if (confirm("Confirm removing " + getCountryName(countryCode) + " from whitelist?")){ 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(); countryCode = countryCode.toLowerCase();
}
if (skipConfirm || confirm("Confirm removing " + getCountryName(countryCode) + " from whitelist?")){
$.cjax({ $.cjax({
url: "/api/whitelist/country/remove", url: "/api/whitelist/country/remove",
method: "POST", method: "POST",
@ -1208,6 +1272,7 @@
if (response.error != undefined){ if (response.error != undefined){
msgbox(response.error, false); msgbox(response.error, false);
} }
msgbox(countryName + " removed from whitelist");
initWhitelistCountryList(); initWhitelistCountryList();
}, },
error: function(xhr, status, error) { error: function(xhr, status, error) {
@ -1276,19 +1341,27 @@
/* /*
Common Utilities Common Utilities
*/ */
function filterCountries(codesToShow, selector="#countrySelector .menu .item") { function filterCountries(alreadySelectedCCs, selector="#countrySelector .menu .item") {
// get all items in the dropdown // get all items in the dropdown
const items = document.querySelectorAll(selector); 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 // loop through all items
items.forEach(item => { items.forEach(item => {
// get the value of the item (i.e. the country code) // get the value of the item (i.e. the country code)
const code = item.dataset.value; const code = item.dataset.value;
// if the code is in the array of codes to show, show the item if (alreadySelectedCCs.includes(code)) {
if (codesToShow.includes(code)) { //This country code already selected. Hide it
item.style.display = 'none'; item.style.display = 'none';
} } else {
// otherwise, hide the item // otherwise, show the item
else {
item.style.display = 'block'; item.style.display = 'block';
} }
}); });

View File

@ -30,7 +30,7 @@
<i class="ui green checkmark icon"></i> Redirection Rule Deleted <i class="ui green checkmark icon"></i> Redirection Rule Deleted
</div> </div>
<!-- Options --> <!-- 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="ui accordion advanceSettings">
<div class="title"> <div class="title">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>

View File

@ -50,7 +50,7 @@
</div> </div>
</div> </div>
<!-- Advance configs --> <!-- 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 id="advanceProxyRules" class="ui fluid accordion">
<div class="title"> <div class="title">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>

View File

@ -94,7 +94,7 @@
<label>Force redirect HTTP request to HTTPS</label> <label>Force redirect HTTP request to HTTPS</label>
</div> </div>
</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="ui accordion advanceSettings">
<div class="title"> <div class="title">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
@ -579,7 +579,7 @@
let timestamps = []; let timestamps = [];
for(var i = 0; i < dataCount; i++){ 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() { function fetchData() {
@ -600,10 +600,8 @@
txValues.shift(); txValues.shift();
} }
timestamps.push(new Date(Date.now()).toLocaleString().replace(',', ''));
timestamps.push(parseInt(Date.now() / 1000));
timestamps.shift(); timestamps.shift();
updateChart(); updateChart();
} }
}) })

View File

@ -69,7 +69,7 @@
</div> </div>
<!-- Advance configs --> <!-- 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 id="advanceProxyRules" class="ui fluid accordion">
<div class="title"> <div class="title">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>

330
src/web/darktheme.css Normal file
View 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;
}

View File

@ -16,8 +16,10 @@
<script src="script/chart.js"></script> <script src="script/chart.js"></script>
<script src="script/utils.js"></script> <script src="script/utils.js"></script>
<link rel="stylesheet" href="main.css"> <link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="darktheme.css">
</head> </head>
<body> <body>
<script src="script/darktheme.js"></script>
<div class="menubar"> <div class="menubar">
<div class="item"> <div class="item">
<img class="logo" src="img/logo.svg"> <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;"> <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> <button class="ui basic white icon button" onclick="logout();"><i class="sign-out icon"></i></button>
</div> </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> <button id="themeColorButton" class="ui icon button" onclick="toggleTheme();"><i class="sun icon"></i></button>
</div> --> </div>
</div> </div>
<div class="wrapper"> <div class="wrapper">
<div class="toolbar"> <div class="toolbar">
@ -269,11 +271,9 @@
function toggleTheme(){ function toggleTheme(){
if ($("body").hasClass("darkTheme")){ if ($("body").hasClass("darkTheme")){
$("body").removeClass("darkTheme") setDarkTheme(false);
$("#themeColorButton").html(`<i class="ui moon icon"></i>`);
}else{ }else{
$("body").addClass("darkTheme"); setDarkTheme(true);
$("#themeColorButton").html(`<i class="ui sun icon"></i>`);
} }
} }

View File

@ -2,13 +2,10 @@
index.html style overwrite index.html style overwrite
*/ */
:root{ :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){ body:not(.darkTheme){
--theme_bg: #f6f6f6; --theme_bg: #f6f6f6;
--theme_bg_primary: #ffffff; --theme_bg_primary: #ffffff;
@ -16,7 +13,7 @@ body:not(.darkTheme){
--theme_bg_active: #ececec; --theme_bg_active: #ececec;
--theme_highlight: #a9d1f3; --theme_highlight: #a9d1f3;
--theme_bg_inverted: #27292d; --theme_bg_inverted: #27292d;
--theme_advance: #f8f8f9; --theme_advance: #f7f7f7;
--item_color: #5e5d5d; --item_color: #5e5d5d;
--item_color_select: rgba(0,0,0,.87); --item_color_select: rgba(0,0,0,.87);
--text_color: #414141; --text_color: #414141;
@ -25,25 +22,35 @@ body:not(.darkTheme){
--text_color_inverted: #fcfcfc; --text_color_inverted: #fcfcfc;
--button_text_color: #878787; --button_text_color: #878787;
--button_border_color: #dedede; --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{ body.darkTheme{
--theme_bg: #27292d; --theme_bg: #000000;
--theme_bg_primary: #3d3f47; --theme_bg_primary: #141414;
--theme_bg_secondary: #373a42; --theme_bg_secondary:#230046;
--theme_highlight: #6682c4; --theme_highlight: #320064;
--theme_bg_active: #292929; --theme_bg_active: #020101;
--theme_bg_inverted: #f8f8f9; --theme_bg_inverted: #f8f8f9;
--theme_advance: #333333; --theme_advance: #000000;
--item_color: #cacaca; --item_color: #cacaca;
--text_color: #fcfcfc; --text_color: #eef1f3;
--text_color_secondary: #dfdfdf; --text_color_secondary: #b5c0c7;
--input_color: black; --input_color: black;
--divider_color: #3b3b3b; --divider_color: #282828;
--item_color_select: rgba(255, 255, 255, 0.87); --item_color_select: rgba(255, 255, 255, 0.87);
--text_color_inverted: #414141; --text_color_inverted: #414141;
--button_text_color: #e9e9e9; --button_text_color: #e9e9e9;
--button_border_color: #646464; --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 */ /* Theme Toggle CSS */
@ -368,7 +375,7 @@ body{
} }
.basic.segment.advanceoptions{ .basic.segment.advanceoptions{
background-color: #f7f7f7; background-color: var(--theme_advance);
border-radius: 1em; border-radius: 1em;
} }

View 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);
}

View File

@ -50,7 +50,7 @@
</div> </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> <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>
<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="ui accordion advanceSettings">
<div class="title"> <div class="title">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
@ -437,11 +437,15 @@
let optionalFieldsHTML = ""; let optionalFieldsHTML = "";
for (const [key, datatype] of Object.entries(data)) { for (const [key, datatype] of Object.entries(data)) {
if (datatype == "int"){ 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;"> <div class="ui basic blue label" style="font-weight: 300;">
${key} ${key}
</div> </div>
<input type="number" value="300"> <input type="number" value="${defaultValue}">
</div>`); </div>`);
}else if (datatype == "bool"){ }else if (datatype == "bool"){
booleanFieldsHTML += (`<div class="ui checkbox dnsConfigField" key="${key}" style="margin-top: 1em !important; padding-left: 0.4em;"> booleanFieldsHTML += (`<div class="ui checkbox dnsConfigField" key="${key}" style="margin-top: 1em !important; padding-left: 0.4em;">
@ -600,8 +604,12 @@
//Boolean option //Boolean option
let checked = $(this).find("input")[0].checked; let checked = $(this).find("input")[0].checked;
dnsCredentials[thisKey] = checked; dnsCredentials[thisKey] = checked;
}else if ($(this).hasClass("typeint")){
//Int options
let value = $(this).find("input").val();
dnsCredentials[thisKey] = parseInt(value);
}else{ }else{
//String or int options //String options
let value = $(this).find("input").val().trim(); let value = $(this).find("input").val().trim();
dnsCredentials[thisKey] = value; dnsCredentials[thisKey] = value;
} }

View File

@ -86,7 +86,7 @@
</div> </div>
</div> </div>
<div class="ui divider"></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="ui fluid accordion">
<div class="title"> <div class="title">
<i class="dropdown icon" tabindex="0"><div class="menu" tabindex="-1"></div></i> <i class="dropdown icon" tabindex="0"><div class="menu" tabindex="-1"></div></i>

View File

@ -6,7 +6,7 @@
*/ */
/* /*
Color definations Color definition
*/ */
:root{ :root{
--dark_theme_toggle: #333333; --dark_theme_toggle: #333333;