⛅ Sync 2026-09-28 20:44:51

This commit is contained in:
github-actions[bot] committed 2026-09-28 20:44:51 +08:00
1 parent 08e60b55f3
commit 38660a8971
8 files changed
+170 -208

No files matched your search

+2 -2
View File
@@ -6,8 +6,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-honk PKG_NAME:=luci-app-honk
PKG_VERSION:=1.1.3 PKG_VERSION:=1.1.4
PKG_RELEASE:=5 PKG_RELEASE:=6
LUCI_TITLE:=LuCI support for honk LUCI_TITLE:=LuCI support for honk
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
+3
View File
@@ -324,3 +324,6 @@ msgstr "面板未启用"
msgid "Dashboard type is currently set to \"None\". Web dashboard and API listener are disabled." msgid "Dashboard type is currently set to \"None\". Web dashboard and API listener are disabled."
msgstr "当前面板类型为“无”,Web 管理面板和 Native API 监听已禁用。" msgstr "当前面板类型为“无”,Web 管理面板和 Native API 监听已禁用。"
msgid "Failed to switch dashboard:"
msgstr "切换面板失败:"
@@ -9,11 +9,6 @@
"file": [ "file": [
"/etc/honk/config.dae", "/etc/honk/config.dae",
"/etc/honk/config.d/*", "/etc/honk/config.d/*",
"/etc/honk/config.d/api.dae",
"/etc/honk/config.d/dns.dae",
"/etc/honk/config.d/node.dae",
"/etc/honk/config.d/route.dae",
"/etc/honk/dashboard/*",
"/etc/honk/doona/*", "/etc/honk/doona/*",
"/etc/honk/zashboard/*" "/etc/honk/zashboard/*"
] ]
@@ -26,11 +21,6 @@
"file": [ "file": [
"/etc/honk/config.dae", "/etc/honk/config.dae",
"/etc/honk/config.d/*", "/etc/honk/config.d/*",
"/etc/honk/config.d/api.dae",
"/etc/honk/config.d/dns.dae",
"/etc/honk/config.d/node.dae",
"/etc/honk/config.d/route.dae",
"/etc/honk/dashboard/*",
"/etc/honk/doona/*", "/etc/honk/doona/*",
"/etc/honk/zashboard/*" "/etc/honk/zashboard/*"
] ]
+90 -131
View File
@@ -5,6 +5,45 @@
import { readfile, writefile, popen, stat } from 'fs'; import { readfile, writefile, popen, stat } from 'fs';
import { cursor } from 'uci'; import { cursor } from 'uci';
const DASHBOARD_DIRS = {
zashboard: "/etc/honk/zashboard",
doona: "/etc/honk/doona"
};
function get_dashboard_dir(type) {
return DASHBOARD_DIRS[type] || DASHBOARD_DIRS.doona;
}
function get_honk_pid() {
let p = popen("pidof honk-core 2>/dev/null");
let pids = p ? p.read("all") : "";
if (p) p.close();
let m = match(pids, /([0-9]+)/);
return m ? m[1] : null;
}
function parse_host_port(addr) {
let res = { host: "", port: "" };
if (!addr) return res;
let m_v6 = match(addr, /^\[([^\]]+)\]:([0-9]+)$/);
let m_v4 = match(addr, /^([^:]+):([0-9]+)$/);
let m_p = match(addr, /^:([0-9]+)$/);
if (m_v6) {
res.host = m_v6[1];
res.port = m_v6[2];
} else if (m_v4) {
res.host = m_v4[1];
res.port = m_v4[2];
} else if (m_p) {
res.host = "0.0.0.0";
res.port = m_p[1];
} else if (match(addr, /^[0-9]+$/)) {
res.host = "0.0.0.0";
res.port = addr;
}
return res;
}
function strip_dae_comments(content) { function strip_dae_comments(content) {
if (!content) return ""; if (!content) return "";
let lines = split(content, /[\r\n]+/); let lines = split(content, /[\r\n]+/);
@@ -40,48 +79,6 @@ function strip_dae_comments(content) {
return join("\n", clean_lines); return join("\n", clean_lines);
} }
function parse_clash_api(clean_content) {
let api_m = match(clean_content, /clash_api\s*\{([^}]+)\}/);
if (!api_m) return null;
let block = api_m[1];
let ec_m = match(block, /external_controller\s*:\s*['"]?([^'" \t\r\n]+)['"]?/);
let ui_m = match(block, /external_ui\s*:\s*['"]?([^'" \t\r\n]+)['"]?/);
let sec_m = match(block, /secret\s*:\s*['"]?([^'" \t\r\n]*)['"]?/);
let dm_m = match(block, /default_mode\s*:\s*['"]?([^'" \t\r\n]*)['"]?/);
let res = {
external_controller: ec_m ? ec_m[1] : "",
external_ui: ui_m ? ui_m[1] : "",
secret: sec_m ? sec_m[1] : "",
default_mode: dm_m ? dm_m[1] : "Rule",
host: "",
port: ""
};
let ec = res.external_controller;
if (ec) {
let m_v6 = match(ec, /^\[([^\]]+)\]:([0-9]+)$/);
let m_v4 = match(ec, /^([^:]+):([0-9]+)$/);
let m_p = match(ec, /^:([0-9]+)$/);
if (m_v6) {
res.host = m_v6[1];
res.port = m_v6[2];
} else if (m_v4) {
res.host = m_v4[1];
res.port = m_v4[2];
} else if (m_p) {
res.host = "0.0.0.0";
res.port = m_p[1];
} else if (match(ec, /^[0-9]+$/)) {
res.host = "0.0.0.0";
res.port = ec;
}
}
return res;
}
function parse_native_api(clean_content) { function parse_native_api(clean_content) {
let api_m = match(clean_content, /native_api\s*\{([^}]+)\}/); let api_m = match(clean_content, /native_api\s*\{([^}]+)\}/);
if (!api_m) return null; if (!api_m) return null;
@@ -107,32 +104,20 @@ function parse_native_api(clean_content) {
port: "" port: ""
}; };
let listen = res.listen; let hp = parse_host_port(res.listen);
if (listen) { res.host = hp.host;
let m_v6 = match(listen, /^\[([^\]]+)\]:([0-9]+)$/); res.port = hp.port;
let m_v4 = match(listen, /^([^:]+):([0-9]+)$/);
let m_p = match(listen, /^:([0-9]+)$/);
if (m_v6) {
res.host = m_v6[1];
res.port = m_v6[2];
} else if (m_v4) {
res.host = m_v4[1];
res.port = m_v4[2];
} else if (m_p) {
res.host = "0.0.0.0";
res.port = m_p[1];
} else if (match(listen, /^[0-9]+$/)) {
res.host = "0.0.0.0";
res.port = listen;
}
}
return res; return res;
} }
function get_config_file_path() { function get_config_file_path() {
let u = cursor(); let u = cursor();
let p = u ? u.get("honk", "config", "config_file") : null; let p = null;
if (u) {
u.load("honk");
p = u.get("honk", "config", "config_file");
}
return p || "/etc/honk/config.dae"; return p || "/etc/honk/config.dae";
} }
@@ -144,21 +129,18 @@ function get_api_config() {
let api_file = get_api_file_path(); let api_file = get_api_file_path();
let content = readfile(api_file) || ""; let content = readfile(api_file) || "";
let clean = strip_dae_comments(content); let clean = strip_dae_comments(content);
let parsed_clash = parse_clash_api(clean);
let parsed_native = parse_native_api(clean); let parsed_native = parse_native_api(clean);
if (!parsed_clash && !parsed_native) { if (!parsed_native) {
let config_file = get_config_file_path(); let config_file = get_config_file_path();
let legacy_content = readfile(config_file) || ""; let legacy_content = readfile(config_file) || "";
let legacy_clean = strip_dae_comments(legacy_content); let legacy_clean = strip_dae_comments(legacy_content);
let leg_clash = parse_clash_api(legacy_clean);
let leg_native = parse_native_api(legacy_clean); let leg_native = parse_native_api(legacy_clean);
if (leg_clash || leg_native) { if (leg_native) {
return { return {
file: config_file, file: config_file,
content: legacy_content, content: legacy_content,
clean: legacy_clean, clean: legacy_clean,
parsed_clash: leg_clash,
parsed_native: leg_native, parsed_native: leg_native,
is_legacy: true is_legacy: true
}; };
@@ -169,7 +151,6 @@ function get_api_config() {
file: api_file, file: api_file,
content: content, content: content,
clean: clean, clean: clean,
parsed_clash: parsed_clash,
parsed_native: parsed_native, parsed_native: parsed_native,
is_legacy: false is_legacy: false
}; };
@@ -225,9 +206,9 @@ function get_dashboard_info(req) {
let u = cursor(); let u = cursor();
let requested_type = (req && req.args) ? req.args.type : null; let requested_type = (req && req.args) ? req.args.type : null;
if (!requested_type && u) { if (!requested_type && u) {
u.load("honk");
requested_type = u.get("honk", "config", "dashboard"); requested_type = u.get("honk", "config", "dashboard");
if (!requested_type) { if (!requested_type) {
u.load("honk");
u.foreach("honk", "honk", function(s) { u.foreach("honk", "honk", function(s) {
if (s.dashboard) requested_type = s.dashboard; if (s.dashboard) requested_type = s.dashboard;
}); });
@@ -236,16 +217,8 @@ function get_dashboard_info(req) {
if (!requested_type) requested_type = "none"; if (!requested_type) requested_type = "none";
let api_cfg = get_api_config(); let api_cfg = get_api_config();
if (!api_cfg.is_legacy) {
clean_legacy_api_from_config(get_config_file_path());
}
let parsed_clash = api_cfg.parsed_clash;
let parsed_native = api_cfg.parsed_native; let parsed_native = api_cfg.parsed_native;
let running = !!get_honk_pid();
let p = popen("pidof honk-core 2>/dev/null");
let pids = p ? p.read("all") : "";
if (p) p.close();
let running = !!match(pids, /[0-9]+/);
let res = { let res = {
dashboard_type: requested_type, dashboard_type: requested_type,
@@ -260,17 +233,16 @@ function get_dashboard_info(req) {
external_ui: "", external_ui: "",
geosite_download_url: "", geosite_download_url: "",
geoip_download_url: "", geoip_download_url: "",
default_mode: "Rule", default_mode: "Rule"
has_clash_api: !!parsed_clash,
has_native_api: !!(parsed_native && parsed_native.enabled)
}; };
if (requested_type == "none") { if (requested_type == "none") {
return res; return res;
} }
let target_default_ui = (requested_type == "zashboard") ? "/etc/honk/zashboard" : "/etc/honk/doona"; let target_default_ui = get_dashboard_dir(requested_type);
let other_default_ui = (requested_type == "zashboard") ? "/etc/honk/doona" : "/etc/honk/zashboard"; let other_type = (requested_type == "zashboard") ? "doona" : "zashboard";
let other_default_ui = get_dashboard_dir(other_type);
if (parsed_native && parsed_native.enabled) { if (parsed_native && parsed_native.enabled) {
res.external_controller = parsed_native.listen; res.external_controller = parsed_native.listen;
@@ -286,14 +258,6 @@ function get_dashboard_info(req) {
} else { } else {
res.configured = false; res.configured = false;
} }
} else if (parsed_clash) {
res.configured = false;
res.external_controller = parsed_clash.external_controller;
res.host = parsed_clash.host;
res.port = parsed_clash.port || "9090";
res.secret = parsed_clash.secret;
res.external_ui = parsed_clash.external_ui;
res.default_mode = parsed_clash.default_mode;
} }
if (res.external_ui) { if (res.external_ui) {
@@ -306,25 +270,35 @@ function get_dashboard_info(req) {
return res; return res;
} }
function download_dashboard(req) { function download_dashboard(req) {
let requested_type = req.args ? req.args.type : null; let requested_type = (req && req.args) ? req.args.type : null;
let url = req.args ? req.args.url : null; if (!requested_type) {
if (!url) { let u = cursor();
if (requested_type == "doona") { if (u) {
url = "https://github.com/Zakkaus/doona/releases/download/v0.1.0-beta.8/doona-0.1.0-beta.8.tar.gz"; u.load("honk");
} else { requested_type = u.get("honk", "config", "dashboard");
url = "https://github.com/Zephyruso/zashboard/releases/latest/download/dist-no-fonts.zip"; if (!requested_type) {
u.foreach("honk", "honk", function(s) {
if (s.dashboard) requested_type = s.dashboard;
});
}
} }
} }
if (!requested_type || requested_type == "none") {
requested_type = "doona";
}
if (!match(url, /^https?:\/\//) || match(url, /[ \t\r\n'"`]/)) { let url = (req && req.args && req.args.url) ? req.args.url : "";
if (url != "" && (!match(url, /^https?:\/\//) || match(url, /[ \t\r\n'"`]/))) {
return { success: false, message: "Invalid URL" }; return { success: false, message: "Invalid URL" };
} }
let api_cfg = get_api_config(); let api_cfg = get_api_config();
let parsed_native = api_cfg.parsed_native; let parsed_native = api_cfg.parsed_native;
let other_default_ui = (requested_type == "zashboard") ? "/etc/honk/doona" : "/etc/honk/zashboard"; let other_type = (requested_type == "zashboard") ? "doona" : "zashboard";
let target_dir = (requested_type == "zashboard") ? "/etc/honk/zashboard" : "/etc/honk/doona"; let other_default_ui = get_dashboard_dir(other_type);
let target_dir = get_dashboard_dir(requested_type) || "/etc/honk/doona";
if (parsed_native && parsed_native.ui && parsed_native.ui != other_default_ui) { if (parsed_native && parsed_native.ui && parsed_native.ui != other_default_ui) {
target_dir = parsed_native.ui; target_dir = parsed_native.ui;
} }
@@ -354,6 +328,18 @@ function switch_dashboard_api(target_type) {
system("mkdir -p /etc/honk/config.d"); system("mkdir -p /etc/honk/config.d");
// 2. Persist UCI dashboard option to keep UCI and api.dae in sync
let u = cursor();
if (u) {
u.load("honk");
let sid = "config";
if (!u.get("honk", sid)) {
u.foreach("honk", "honk", function(s) { sid = s[".name"]; });
}
u.set("honk", sid, "dashboard", target_type || "none");
u.commit("honk");
}
if (target_type == "none" || !target_type) { if (target_type == "none" || !target_type) {
let cur = readfile(api_file); let cur = readfile(api_file);
if (cur && trim(cur) != "") { if (cur && trim(cur) != "") {
@@ -366,14 +352,12 @@ function switch_dashboard_api(target_type) {
} }
let api_cfg = get_api_config(); let api_cfg = get_api_config();
let parsed_clash = api_cfg.parsed_clash;
let parsed_native = api_cfg.parsed_native; let parsed_native = api_cfg.parsed_native;
let target_ui = get_dashboard_dir(target_type);
let target_ui = (target_type == "zashboard") ? "/etc/honk/zashboard" : "/etc/honk/doona";
// Check if already correctly configured in api.dae // Check if already correctly configured in api.dae
if (!api_cfg.is_legacy) { if (!api_cfg.is_legacy) {
if (parsed_native && parsed_native.enabled && !parsed_clash && if (parsed_native && parsed_native.enabled &&
parsed_native.listen && parsed_native.listen &&
parsed_native.config_write && parsed_native.config_write &&
parsed_native.geosite_download_url && parsed_native.geoip_download_url && parsed_native.geosite_download_url && parsed_native.geoip_download_url &&
@@ -429,11 +413,7 @@ return {
"luci.honk": { "luci.honk": {
status: { status: {
call: function(req) { call: function(req) {
let p = popen("pidof honk-core 2>/dev/null"); let pid = get_honk_pid();
let pids = p ? p.read("all") : "";
if (p) p.close();
let m = match(pids, /([0-9]+)/);
let pid = m ? m[1] : null;
let running = !!pid; let running = !!pid;
let memory = null; let memory = null;
if (running) { if (running) {
@@ -484,20 +464,11 @@ return {
call: get_dashboard_info call: get_dashboard_info
}, },
get_zashboard_info: {
call: get_dashboard_info
},
download_dashboard: { download_dashboard: {
args: { url: "string", type: "string" }, args: { url: "string", type: "string" },
call: download_dashboard call: download_dashboard
}, },
download_zashboard: {
args: { url: "string", type: "string" },
call: download_dashboard
},
download_status: { download_status: {
call: function(req) { call: function(req) {
let status_raw = readfile("/tmp/honk_dashboard_download.status") || "IDLE"; let status_raw = readfile("/tmp/honk_dashboard_download.status") || "IDLE";
@@ -508,18 +479,6 @@ return {
} }
}, },
enable_clash_api: {
call: function(req) {
return switch_dashboard_api("zashboard");
}
},
enable_native_api: {
call: function(req) {
return switch_dashboard_api("doona");
}
},
switch_dashboard_api: { switch_dashboard_api: {
args: { type: "string" }, args: { type: "string" },
call: function(req) { call: function(req) {
@@ -76,9 +76,6 @@ var callHonkDownloadDashboard = rpc.declare({
expect: { } expect: { }
}); });
var callHonkZashboardInfo = callHonkDashboardInfo;
var callHonkDownloadZashboard = callHonkDownloadDashboard;
var callHonkDownloadStatus = rpc.declare({ var callHonkDownloadStatus = rpc.declare({
object: 'luci.honk', object: 'luci.honk',
method: 'download_status', method: 'download_status',
@@ -92,6 +89,13 @@ var callHonkSwitchDashboardApi = rpc.declare({
expect: { } expect: { }
}); });
var callUciGet = rpc.declare({
object: 'uci',
method: 'get',
params: [ 'config', 'section', 'option' ],
expect: { value: '' }
});
function readFile(path) { function readFile(path) {
if (fs.read_direct) { if (fs.read_direct) {
return fs.read_direct(path).catch(function() { return fs.read_direct(path).catch(function() {
@@ -173,16 +177,23 @@ function ensureEditorStyles() {
document.head.appendChild(style); document.head.appendChild(style);
} }
var _cmPromise = null;
function ensureCodeMirror() { function ensureCodeMirror() {
if (_cmPromise) {
return _cmPromise;
}
loadStyle(L.resource('honk/lib/codemirror.css')); loadStyle(L.resource('honk/lib/codemirror.css'));
loadStyle(L.resource('honk/addon/fold/foldgutter.css')); loadStyle(L.resource('honk/addon/fold/foldgutter.css'));
ensureEditorStyles(); ensureEditorStyles();
if (window.CodeMirror && window.CodeMirror.modes && window.CodeMirror.modes.dae) { if (window.CodeMirror && window.CodeMirror.modes && window.CodeMirror.modes.dae) {
return Promise.resolve(window.CodeMirror); _cmPromise = Promise.resolve(window.CodeMirror);
return _cmPromise;
} }
return loadScript(L.resource('honk/lib/codemirror.js')) _cmPromise = loadScript(L.resource('honk/lib/codemirror.js'))
.then(function() { .then(function() {
return Promise.all([ return Promise.all([
loadScript(L.resource('honk/addon/edit/matchbrackets.js')), loadScript(L.resource('honk/addon/edit/matchbrackets.js')),
@@ -195,7 +206,12 @@ function ensureCodeMirror() {
}) })
.then(function() { .then(function() {
return window.CodeMirror; return window.CodeMirror;
}).catch(function(err) {
_cmPromise = null;
throw err;
}); });
return _cmPromise;
} }
function formatEditor(ed) { function formatEditor(ed) {
@@ -442,60 +458,57 @@ function createConfigFileView(filePath, mapTitle, mapDesc, fieldTitle, successMs
} }
// Advanced-only tabs: these paths are hidden when advanced=0. // Tab visibility control:
// This runs on every honk page render and reads live UCI values, // - dns, node, route are hidden when advanced=0
// bypassing LuCI's sessionStorage menu cache entirely. // - api is hidden when dashboard=none
var ADVANCED_TAB_PATHS = ['/honk/dns', '/honk/node', '/honk/route']; function applyTabVisibility() {
return Promise.all([
L.resolveDefault(callUciGet('honk', 'config', 'advanced'), '0'),
L.resolveDefault(callUciGet('honk', 'config', 'dashboard'), 'none')
]).then(function(res) {
var isAdvanced = (res[0] === '1');
var dashType = res[1] || 'none';
function applyAdvancedTabVisibility() { var hiddenTabs = [];
// Use ubus directly to read the committed UCI value (not the in-memory
// JS UCI module, which may have pending unsaved changes).
return L.resolveDefault(
rpc.declare({
object: 'uci',
method: 'get',
params: ['config', 'section', 'option'],
expect: { value: '' }
})('honk', 'config', 'advanced'),
''
).then(function(val) {
var isAdvanced = (val === '1');
applyTabCss(isAdvanced);
if (!isAdvanced) { if (!isAdvanced) {
var isAdvPage = (window.L && L.env && Array.isArray(L.env.dispatchpath) && ['dns', 'node', 'route'].indexOf(L.env.dispatchpath[3]) !== -1) || hiddenTabs.push('dns', 'node', 'route');
ADVANCED_TAB_PATHS.some(function(p) { return window.location.pathname.replace(/\/+$/, '').endsWith(p); }); }
if (isAdvPage) { if (dashType === 'none') {
window.location.href = L.url('admin/services/honk/global'); hiddenTabs.push('api');
} }
applyTabCss(hiddenTabs);
var currentTab = (window.L && L.env && Array.isArray(L.env.dispatchpath)) ? L.env.dispatchpath[3] : '';
if (!currentTab) {
var m = window.location.pathname.match(/\/honk\/([a-z0-9_-]+)/);
if (m) currentTab = m[1];
}
if (currentTab && hiddenTabs.indexOf(currentTab) !== -1) {
window.location.href = L.url('admin/services/honk/global');
} }
}).catch(function() { }).catch(function() {
}); });
} }
function applyTabCss(isAdvanced) { var applyAdvancedTabVisibility = applyTabVisibility;
// Inject a style element that hides advanced-only tab items and links.
// This is idempotent and works seamlessly across themes (Bootstrap, Aurora, etc.). function applyTabCss(hiddenTabs) {
var styleId = 'honk-adv-tab-style'; var styleId = 'honk-tab-visibility-style';
var existing = document.getElementById(styleId); var existing = document.getElementById(styleId);
if (!existing) { if (!existing) {
existing = document.createElement('style'); existing = document.createElement('style');
existing.id = styleId; existing.id = styleId;
document.head.appendChild(existing); document.head.appendChild(existing);
} }
if (isAdvanced) { if (!hiddenTabs || hiddenTabs.length === 0) {
existing.textContent = ''; existing.textContent = '';
} else { } else {
existing.textContent = [ existing.textContent = hiddenTabs.map(function(tab) {
'#tabmenu .tabmenu-item-dns,', return '#tabmenu .tabmenu-item-' + tab + ',\n' +
'#tabmenu .tabmenu-item-node,', '.tabmenu-item-' + tab + ',\n' +
'#tabmenu .tabmenu-item-route,', '#tabmenu a[href$="/honk/' + tab + '"]';
'.tabmenu-item-dns,', }).join(',\n') + ' { display: none !important; }';
'.tabmenu-item-node,',
'.tabmenu-item-route,',
'#tabmenu a[href$="/honk/dns"],',
'#tabmenu a[href$="/honk/node"],',
'#tabmenu a[href$="/honk/route"] { display: none !important; }'
].join('\n');
} }
} }
@@ -557,26 +570,22 @@ function renderStatusHeader() {
return callHonkStatus().then(updateStatus); return callHonkStatus().then(updateStatus);
}, 3); }, 3);
// Apply tab visibility based on live UCI advanced value. applyTabVisibility();
// This runs asynchronously after render; the CSS injection is fast enough
// that tabs flicker is imperceptible (tabs hide before user can click them).
applyAdvancedTabVisibility();
return section; return section;
} }
return baseclass.extend({ return baseclass.extend({
applyAdvancedTabVisibility: applyAdvancedTabVisibility, applyTabVisibility: applyTabVisibility,
applyAdvancedTabVisibility: applyTabVisibility,
callHonkStatus: callHonkStatus, callHonkStatus: callHonkStatus,
callHonkReload: callHonkReload, callHonkReload: callHonkReload,
callHonkRestart: callHonkRestart, callHonkRestart: callHonkRestart,
callHonkGetLog: callHonkGetLog, callHonkGetLog: callHonkGetLog,
callHonkClearLog: callHonkClearLog, callHonkClearLog: callHonkClearLog,
callHonkDashboardInfo: callHonkDashboardInfo, callHonkDashboardInfo: callHonkDashboardInfo,
callHonkZashboardInfo: callHonkDashboardInfo,
callHonkDownloadDashboard: callHonkDownloadDashboard, callHonkDownloadDashboard: callHonkDownloadDashboard,
callHonkDownloadZashboard: callHonkDownloadDashboard,
callHonkDownloadStatus: callHonkDownloadStatus, callHonkDownloadStatus: callHonkDownloadStatus,
callHonkSwitchDashboardApi: callHonkSwitchDashboardApi, callHonkSwitchDashboardApi: callHonkSwitchDashboardApi,
readFile: readFile, readFile: readFile,
@@ -17,8 +17,9 @@ return view.extend({
}, },
render: function() { render: function() {
if (honk && honk.applyAdvancedTabVisibility) { var applyTabs = (honk && (honk.applyTabVisibility || honk.applyAdvancedTabVisibility));
honk.applyAdvancedTabVisibility(); if (applyTabs) {
applyTabs();
} }
var sec = (uci.sections('honk', 'honk')[0] || {}); var sec = (uci.sections('honk', 'honk')[0] || {});
var sid = sec['.name'] || 'config'; var sid = sec['.name'] || 'config';
@@ -85,13 +86,12 @@ return view.extend({
'style': 'margin-right: 10px;', 'style': 'margin-right: 10px;',
'change': function(ev) { 'change': function(ev) {
var newType = ev.target.value; var newType = ev.target.value;
uci.set('honk', sid, 'dashboard', newType); sel.disabled = true;
uci.save().then(function() { honk.callHonkSwitchDashboardApi(newType).then(function() {
return uci.apply();
}).then(function() {
return honk.callHonkSwitchDashboardApi(newType);
}).then(function() {
window.location.reload(); window.location.reload();
}).catch(function(err) {
sel.disabled = false;
honk.showNotification(null, E('p', _('Failed to switch dashboard:') + ' ' + (err.message || err)), 'error');
}); });
} }
}); });
@@ -62,6 +62,8 @@ return view.extend({
var newDash = uci.get('honk', sid, 'dashboard') || 'none'; var newDash = uci.get('honk', sid, 'dashboard') || 'none';
if (newDash !== oldDash) { if (newDash !== oldDash) {
return honk.callHonkSwitchDashboardApi(newDash); return honk.callHonkSwitchDashboardApi(newDash);
} else {
return honk.callHonkReload();
} }
}).then(function() { }).then(function() {
return ui.changes.apply(mode == '0'); return ui.changes.apply(mode == '0');
@@ -10,8 +10,9 @@ return view.extend({
handleReset: null, handleReset: null,
render: function() { render: function() {
if (honk && honk.applyAdvancedTabVisibility) { var applyTabs = (honk && (honk.applyTabVisibility || honk.applyAdvancedTabVisibility));
honk.applyAdvancedTabVisibility(); if (applyTabs) {
applyTabs();
} }
var scrolled = false; var scrolled = false;
@@ -35,12 +36,10 @@ return view.extend({
logTextarea.value = ''; logTextarea.value = '';
logTextarea.scrollTop = 0; logTextarea.scrollTop = 0;
scrolled = false; scrolled = false;
var notify = (honk && honk.showNotification) ? honk.showNotification : ui.addNotification; honk.showNotification(null, E('p', _('Logs cleared successfully.')), 'info');
notify(null, E('p', _('Logs cleared successfully.')), 'info');
}).catch(function(err) { }).catch(function(err) {
btnClear.disabled = false; btnClear.disabled = false;
var notify = (honk && honk.showNotification) ? honk.showNotification : ui.addNotification; honk.showNotification(null, E('p', _('Failed to clear logs:') + ' ' + (err.message || err)), 'error');
notify(null, E('p', _('Failed to clear logs:') + ' ' + (err.message || err)), 'error');
}); });
} }
}, _('Clear logs')); }, _('Clear logs'));