From 13b9d15d8f9d65a0275197d6d1105eaac24fcf31 Mon Sep 17 00:00:00 2001 From: Donald Cheng Hong Zou Date: Thu, 21 Apr 2022 15:11:01 -0400 Subject: [PATCH] New darkmode theme --- src/api.py | 20 ++++- src/dashboard.py | 33 ++++---- src/static/css/dashboard.css | 8 ++ src/static/css/theme/dark.css | 123 +++++++++++++++++++++++++++++ src/static/js/configuration.js | 13 ++- src/static/js/configurationTool.js | 18 +++-- src/templates/configuration.html | 2 +- src/templates/header.html | 1 + src/templates/index.html | 1 - src/templates/modal.html | 105 ++++++++++++++++++++++++ src/templates/sidebar.html | 1 - 11 files changed, 297 insertions(+), 28 deletions(-) create mode 100644 src/static/css/theme/dark.css diff --git a/src/api.py b/src/api.py index 46e2362..8fe189a 100644 --- a/src/api.py +++ b/src/api.py @@ -2,10 +2,15 @@ import ipaddress, subprocess, datetime, os, util from datetime import datetime, timedelta from flask import jsonify from util import * +import configparser notEnoughParameter = {"status": False, "reason": "Please provide all required parameters."} good = {"status": True, "reason": ""} +def ret(status=True, reason="", data=""): + return {"status": status, "reason": reason, "data": data} + + def togglePeerAccess(data, g): checkUnlock = g.cur.execute(f"SELECT * FROM {data['config']} WHERE id='{data['peerID']}'").fetchone() @@ -70,7 +75,7 @@ class managePeer: }) return {"status": True, "reason": "", "data": chartData} -class addConfiguration: +class manageConfiguration: def AddressCheck(self, data): address = data['address'] address = address.replace(" ", "") @@ -165,4 +170,15 @@ class addConfiguration: except Exception as e: return {"status": False, "reason": "Can't delete peer", "data": str(e)} - return good \ No newline at end of file + return good + + def getConfigurationInfo(self, configName, WG_CONF_PATH): + conf = configparser.ConfigParser(strict=False) + try: + with open(f'{WG_CONF_PATH}/{configName}.conf', 'r'): + conf.read(f'{WG_CONF_PATH}/{configName}.conf') + if not conf.has_section("Interface"): + return ret(status=False, reason="No [Interface] in configuration file") + return ret(data=dict(conf['Interface'])) + except FileNotFoundError as err: + return ret(status=False, reason=str(err)) \ No newline at end of file diff --git a/src/dashboard.py b/src/dashboard.py index 55362a6..2d07e4d 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -3,6 +3,7 @@ Under Apache-2.0 License """ +from crypt import methods import sqlite3 import configparser import hashlib @@ -1599,7 +1600,7 @@ def addConfigurationAddressCheck(): returnData = {"status": True, "reason": ""} required = ['address'] if checkJSONAllParameter(required, data): - returnData = api.addConfiguration.AddressCheck(api.addConfiguration, data) + returnData = api.manageConfiguration.AddressCheck(api.manageConfiguration, data) else: return jsonify(api.notEnoughParameter) return jsonify(returnData) @@ -1610,7 +1611,7 @@ def addConfigurationPortCheck(): returnData = {"status": True, "reason": ""} required = ['port'] if checkJSONAllParameter(required, data): - returnData = api.addConfiguration.PortCheck(api.addConfiguration, data, get_conf_list()) + returnData = api.manageConfiguration.PortCheck(api.manageConfiguration, data, get_conf_list()) else: return jsonify(api.notEnoughParameter) return jsonify(returnData) @@ -1621,7 +1622,7 @@ def addConfigurationNameCheck(): returnData = {"status": True, "reason": ""} required = ['name'] if checkJSONAllParameter(required, data): - returnData = api.addConfiguration.NameCheck(api.addConfiguration, data, get_conf_list()) + returnData = api.manageConfiguration.NameCheck(api.manageConfiguration, data, get_conf_list()) else: return jsonify(api.notEnoughParameter) return jsonify(returnData) @@ -1641,36 +1642,40 @@ def addConfiguration(): if i not in data.keys(): return jsonify(api.notEnoughParameter) config = get_conf_list() - nameCheck = api.addConfiguration.NameCheck(api.addConfiguration, {"name": data['addConfigurationName']}, config) + nameCheck = api.manageConfiguration.NameCheck(api.manageConfiguration, {"name": data['addConfigurationName']}, config) if not nameCheck['status']: return nameCheck - portCheck = api.addConfiguration.PortCheck(api.addConfiguration, {"port": data['addConfigurationListenPort']}, config) + portCheck = api.manageConfiguration.PortCheck(api.manageConfiguration, {"port": data['addConfigurationListenPort']}, config) if not portCheck['status']: return portCheck - addressCheck = api.addConfiguration.AddressCheck(api.addConfiguration, {"address": data['addConfigurationAddress']}) + addressCheck = api.manageConfiguration.AddressCheck(api.manageConfiguration, {"address": data['addConfigurationAddress']}) if not addressCheck['status']: return addressCheck - returnData = api.addConfiguration.addConfiguration(api.addConfiguration, data, config, WG_CONF_PATH) + returnData = api.manageConfiguration.addConfiguration(api.manageConfiguration, data, config, WG_CONF_PATH) return jsonify(returnData) @app.route('/api/deleteConfiguration', methods=['POST']) def deleteConfiguration(): data = request.get_json() - returnData = {"status": True, "reason": "", "data":""} required = ['name'] if not checkJSONAllParameter(required, data): return jsonify(api.notEnoughParameter) - - returnData = api.addConfiguration.deleteConfiguration(api.addConfiguration, data, get_conf_list(), g, WG_CONF_PATH) - - - - + returnData = api.manageConfiguration.deleteConfiguration(api.manageConfiguration, data, get_conf_list(), g, WG_CONF_PATH) return returnData +@app.route('/api/getConfigurationInfo', methods=['GET']) +def getConfigurationInfo(): + data = request.args.to_dict() + required = ['configName'] + if not checkJSONAllParameter(required, data): + return jsonify(api.notEnoughParameter) + else: + return api.manageConfiguration.getConfigurationInfo(api.manageConfiguration, data['configName'], WG_CONF_PATH) + + """ Dashboard Tools Related """ diff --git a/src/static/css/dashboard.css b/src/static/css/dashboard.css index 00a79b1..54a5f9a 100644 --- a/src/static/css/dashboard.css +++ b/src/static/css/dashboard.css @@ -173,6 +173,10 @@ body { margin: 0 1rem 0 0; } +.btn-control:hover{ + background-color: transparent !important; +} + .btn-control:active, .btn-control:focus { background-color: transparent !important; @@ -914,4 +918,8 @@ pre.index-alert { .sb-update-url .dot-running{ transform: translateX(10px); +} + +.list-group-item{ + transition: all 0.1s ease-in; } \ No newline at end of file diff --git a/src/static/css/theme/dark.css b/src/static/css/theme/dark.css new file mode 100644 index 0000000..c47e957 --- /dev/null +++ b/src/static/css/theme/dark.css @@ -0,0 +1,123 @@ +:root{ + --blue: #3f9eff; + --dark1: #1C1C1E; + --dark2: #232323; + --dark3: #3f3f3f; +} + +a{ + color: var(--blue); +} + +body{ + background-color: var(--dark1); + color: #ffffff; +} + +hr{ + border-top: 1px solid rgb(255 255 255 / 10%); +} + +/* Color */ + +.bg-dark{ + background-color: #232323!important; +} + +.text-primary{ + color: var(--blue) !important; +} + +/* Form Related */ + +.form-control{ + color: #ffffff; + background-color: #232323; + border: 1px solid #686868; +} + +.form-control:focus { + color: #ffffff; + background-color: #232323; + border-color: #686868; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 0.50); +} + +.form-control:disabled, .form-control[readonly]{ + background-color: #525252; + opacity: 1; + color: #a5a5a5; +} + +.custom-control-label::before{ + background-color: transparent; +} + +/* Side Bar */ + +.sidebar{ + background-color: #232323 !important; +} + +.sidebar .nav-link, .bottomNavContainer .nav-link{ + color: #dddddd; +} + +.sidebar .nav-link.active, .bottomNavContainer .nav-link.active{ + color: var(--blue) !important; +} + +.nav-link:hover{ + background-color: #3f3f3f; +} + +.card{ + background-color: #232323; +} + + +/* Button Related */ + +.btn-outline-primary{ + color: var(--blue); + border-color: var(--blue); +} + +.btn-outline-primary:hover { + color: #fff; + background-color: var(--blue); + border-color: var(--blue); +} + +.btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active, .show>.btn-outline-primary.dropdown-toggle{ + background-color: var(--blue); + border-color: var(--blue); +} + + +/* Configuration Card (index.html) */ +.conf_card:hover{ + border-color: var(--blue); +} + +/* Modal */ +.modal-content{ + background-color: var(--dark1); +} + +.modal-header, .modal-footer{ + border-color:rgb(255 255 255 / 10%);; +} + +/* List Group Item */ +.list-group-item{ + background-color: var(--dark2); + color: white; +} + +.list-group-item:hover{ + color: white; + background-color: var(--dark3); + border-color: var(--dark3); +} \ No newline at end of file diff --git a/src/static/js/configuration.js b/src/static/js/configuration.js index c10e04e..2137d11 100644 --- a/src/static/js/configuration.js +++ b/src/static/js/configuration.js @@ -8,7 +8,7 @@ let peers = []; /** * Definitions */ - $(".bottomNavConfigs").addClass("active") + $(".bottomNavConfigs").addClass("active"); let configuration_name; let configuration_interval; let configuration_timeout = window.localStorage.getItem("configurationTimeout"); @@ -38,6 +38,7 @@ let peers = []; let settingModal = new bootstrap.Modal(document.getElementById('setting_modal'), bootstrapModalConfig); let deleteModal = new bootstrap.Modal(document.getElementById('delete_modal'), bootstrapModalConfig); let configurationDeleteModal = new bootstrap.Modal(document.getElementById('configuration_delete_modal'), bootstrapModalConfig); + let configurationEditModal = new bootstrap.Modal(document.getElementById('editConfigurationModal'), bootstrapModalConfig); let peerDataUsageModal = new bootstrap.Modal(document.getElementById('peerDataUsage'), bootstrapModalConfig); $("[data-toggle='tooltip']").tooltip(); $("[data-toggle='popover']").popover(); @@ -977,6 +978,13 @@ let peers = []; }); } + function getConfigurationDetails() { + function done(res){ + console.log(res); + } + ajaxGetJSON(`/api/getConfigurationInfo?configName=${configuration_name}`, done) + } + configurations = { peerDataUsageChartObj: () => { return peerDataUsageChartObj }, peerDataUsageModal: () => { return peerDataUsageModal }, @@ -987,6 +995,7 @@ let peers = []; ipModal: () => { return ipModal; }, qrcodeModal: () => { return qrcodeModal; }, settingModal: () => { return settingModal; }, + configurationEditModal: () => { return configurationEditModal; }, configurationTimeout: () => { return configuration_timeout; }, updateDisplayMode: () => { display_mode = window.localStorage.getItem("displayMode"); }, removeConfigurationInterval: () => { removeConfigurationInterval(); }, @@ -998,7 +1007,7 @@ let peers = []; parsePeers: (response) => { parsePeers(response); }, toggleAccess: (peerID) => { toggleAccess(peerID); }, - + getConfigurationDetails: () => { getConfigurationDetails() }, setConfigurationName: (confName) => { configuration_name = confName; }, getConfigurationName: () => { return configuration_name; }, setActiveConfigurationName: () => { setActiveConfigurationName(); }, diff --git a/src/static/js/configurationTool.js b/src/static/js/configurationTool.js index 66bf8ec..355b95f 100644 --- a/src/static/js/configurationTool.js +++ b/src/static/js/configurationTool.js @@ -1,5 +1,3 @@ - - let $body = $("body"); let available_ips = []; let $add_peer = document.getElementById("save_peer"); @@ -89,11 +87,6 @@ $body.on("click", ".btn-data-usage-peer", function(){ ajaxPostJSON("/api/getPeerDataUsage", {"config": configurations.getConfigurationName(), "peerID": configurations.peerDataUsageChartObj().data.peerID, "interval": window.localStorage.getItem("peerTimePeriod")}, loadPeerDataUsageChartDone); }); - - - - - $('#peerDataUsage').on('shown.bs.modal', function() { configurations.peerDataUsageChartObj().resize(); }).on('hidden.bs.modal', function() { @@ -117,6 +110,17 @@ $(".switchTimePeriod").on("click", function(){ }) +/** + * Edit Configuration + */ + +$editConfiguration = $("#edit_configuration"); +$editConfiguration.on("click", function(){ + configurations.getConfigurationDetails(); + configurations.configurationEditModal().toggle(); +}); + + /** * ========== * Add peers diff --git a/src/templates/configuration.html b/src/templates/configuration.html index 9def19a..c5a5c4d 100644 --- a/src/templates/configuration.html +++ b/src/templates/configuration.html @@ -170,7 +170,7 @@ data-url="/download_all/{{conf_data['name']}}"> Download All Peers
- + Configration Settings Delete Configuration diff --git a/src/templates/header.html b/src/templates/header.html index 4dd70d1..85f825f 100644 --- a/src/templates/header.html +++ b/src/templates/header.html @@ -14,6 +14,7 @@ + diff --git a/src/templates/index.html b/src/templates/index.html index 95329a0..16c7e46 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -123,7 +123,6 @@ -
diff --git a/src/templates/modal.html b/src/templates/modal.html index 0acbab0..c60caef 100644 --- a/src/templates/modal.html +++ b/src/templates/modal.html @@ -354,4 +354,109 @@
+ + \ No newline at end of file diff --git a/src/templates/sidebar.html b/src/templates/sidebar.html index bc4e632..3f24d2b 100644 --- a/src/templates/sidebar.html +++ b/src/templates/sidebar.html @@ -62,7 +62,6 @@ -