Files
op-packages/luci-app-openclash/luasrc/view/openclash/tblsection.htm
T

570 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<%-
local rowcnt = 1
local uci = require("luci.model.uci").cursor()
local fs = require "luci.openclash"
function rowstyle()
rowcnt = rowcnt + 1
return (rowcnt % 2) + 1
end
function width(o)
if o.width then
if type(o.width) == 'number' then
return ' style="width:%dpx"' % o.width
end
return ' style="width:%s"' % o.width
end
return ''
end
function table_include(table, value)
if table == nil then
return false
end
for k, v in pairs(table) do
if v == value then
return true
end
end
return false
end
local a={}
local e={}
if self.sectiontype == "dns_servers" then
table.insert(e, {name="nameserver", title="nameserver"})
table.insert(e, {name="fallback", title="fallback"})
table.insert(e, {name="default", title="default-nameserver"})
else
for t,o in ipairs(fs.glob("/etc/openclash/config/*"))do
a=fs.stat(o)
if a then
e[t]={}
e[t].name=fs.basename(o)
end
end
if not table_include(e, "all") then
table.insert(e, 1, {name="all"})
end
end
local cfg_name
if os.getenv("PATH_INFO") then
local cfg_path = string.match(os.getenv("PATH_INFO"), "/config/(.+)$")
cfg_name = cfg_path and string.match(cfg_path, "([^/]+)$") or nil
end
if not cfg_name and uci:get("openclash", "config", "config_path") then
cfg_name = fs.basename(uci:get("openclash", "config", "config_path"))
end
local sectiontype = "_"..self.config.."_"..string.match(self.sectiontype, "[%w_]+") or "self.sectiontype"
-%>
<style type="text/css">
*{margin: 0;padding: 0;}
ul{
list-style: none;
}
h3{
margin-top: 0;
}
.cbi-value-field .cbi-dropdown, .cbi-value-field .cbi-input-select, .cbi-value input[type="text"], .cbi-value input[type="password"] {
min-width: auto;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%>{
display: flex;
align-items: center;
justify-content: flex-start;
padding: 16px 20px;
border-bottom: 1px solid var(--border-light, #e2e8f0);
background: var(--bg-gray, #f1f5f9);
min-width: 0;
box-shadow: none;
position: relative;
z-index: 1;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul{
display: flex;
width: 100%;
background: #f1f5f9;
border-radius: 8px;
border-bottom: none !important;
border: none !important;
gap: 5px;
margin: 0;
padding: 0;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li{
flex: 1 1 0;
min-width: 120px;
max-width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px 0;
height: 100%;
font-size: 13px;
font-weight: 400;
color: #64748b;
background: transparent;
border: 1px solid #e2e8f0;
border-radius: 8px;
cursor: pointer;
transition: all 0.18s;
margin: 0;
user-select: none;
position: relative;
box-sizing: border-box;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab{
background: #3b82f6;
color: #fff;
font-weight: 600;
z-index: 2;
border-radius: 6px;
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.03);
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li a{
display: block;
width: 100%;
height: 100%;
text-align: center;
text-decoration: none;
background: none;
border: none;
outline: none;
font: inherit;
color: inherit;
cursor: inherit;
padding: 5px;
margin: 0;
user-select: none;
transition: color 0.18s;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab > a{
color: #fff !important;
font-weight: 500;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled{
color: #fff;
background: #f9f9f9;
opacity: 0.7;
cursor: pointer;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled a{
color: #000 !important;
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover,
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus{
color: #3b82f6;
background: rgba(59,130,246,0.10);
}
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover a,
#tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus a{
color: #3b82f6 !important;
}
#tab-content .dom-<%=self.config%>-<%=self.sectiontype%>{
display: none;
}
#tab-content .dom-<%=self.config%>-<%=self.sectiontype%> ul li{
float: left;
margin: 15px 10px;
width: 225px;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%>{
background: #374151;
border-bottom: 1px solid #374151;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul{
background: #374151;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li{
background: #1f2937;
color: #a1a1aa;
border-color: #374151;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab{
background: #2563eb;
color: #fff;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab a{
color: #fff !important;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled{
color: #1f2937;
background: #1f2937;
opacity: 0.7;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled a{
color: #fff !important;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover,
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus{
color: #3b82f6;
border-color: #3b82f6;
background: #22304a;
}
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover a,
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus a{
color: #60a5fa !important;
}
</style>
<!-- tblsection -->
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<%- if self.title and #self.title > 0 then -%>
<h3><%=self.title%></h3>
<%- end -%>
<%- if self.sortable then -%>
<input type="hidden" id="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" name="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" value="" />
<%- end -%>
<div class="cbi-section-descr"><%=self.description%></div>
<%- local count = 0 -%>
<div id="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tabmenu">
<ul class="cbi-tabmenu">
<%-
if self.sectiontype == "dns_servers" then
for i, tab in ipairs(e) do
if i == 1 then
-%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab" data-group="<%=tab.name%>"><a title="<%=tab.name%>"><%=tab.title%></a></li>
<%- else -%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab-disabled" data-group="<%=tab.name%>"><a title="<%=tab.name%>"><%=tab.title%></a></li>
<%- end -%>
<%- end -%>
<%- elseif #e ~= 1 then
for i, tab in ipairs(e) do
if tab.name == cfg_name and cfg_name then
-%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab" data-group="<%=tab.name%>"><a title="<%=tab.name%>"><%=tab.name%></a></li>
<%- elseif not cfg_name and tab.name == "all" then -%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab" data-group="<%=tab.name%>"><a title="All">ALL</a></li>
<%- elseif tab.name == "all" then -%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab-disabled" data-group="<%=tab.name%>"><a title="All">ALL</a></li>
<%- else -%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab-disabled" data-group="<%=tab.name%>"><a title="<%=tab.name%>"><%=tab.name%></a></li>
<%- end -%>
<%- end -%>
<%- else -%>
<li name="tab-header-<%=self.config%>-<%=self.sectiontype%>" class="cbi-tab" data-group="all"><a title="All">ALL</a></li>
<%- end -%>
</ul>
</div>
<div id="tab-content">
<%- for i, tab in ipairs(e) do
if self.sectiontype == "dns_servers" then
if tab.name == "nameserver" then
-%>
<div class="dom-<%=self.config%>-<%=self.sectiontype%>" style="display: block;" data-group="<%=tab.name%>">
<%- else -%>
<div class="dom-<%=self.config%>-<%=self.sectiontype%>" data-group="<%=tab.name%>">
<%- end -%>
<%- elseif #e ~= 1 and tab.name == cfg_name and cfg_name then -%>
<div class="dom-<%=self.config%>-<%=self.sectiontype%>" style="display: block;" data-group="<%=tab.name%>">
<%- elseif #e ~= 1 and tab.name == "all" and not cfg_name then -%>
<div class="dom-<%=self.config%>-<%=self.sectiontype%>" style="display: block;" data-group="<%=tab.name%>">
<%- elseif #e == 1 then -%>
<div class="dom-<%=self.config%>-<%=self.sectiontype%>" style="display: block;" data-group="all">
<%- else -%>
<div class="dom-<%=self.config%>-<%=self.sectiontype%>" data-group="<%=tab.name%>">
<%- end -%>
<table class="table cbi-section-table">
<tr class="tr cbi-section-table-titles">
<%- if not self.anonymous then -%>
<%- if self.sectionhead then -%>
<th class="th cbi-section-table-cell"><%=self.sectionhead%></th>
<%- else -%>
<th>&#160;</th>
<%- end -%>
<%- end -%>
<%- for i, k in pairs(self.children) do if not k.optional then -%>
<%- if i == 1 then -%>
<th class="th cbi-section-table-cell"><%:Serial Number%></th>
<%- end -%>
<th class="th cbi-section-table-cell"<%=width(k)%>>
<%- if k.titleref then -%><a title="<%=self.titledesc or translate('Go to relevant configuration page')%>" class="cbi-title-ref" href="<%=k.titleref%>"><%- end -%>
<%-=k.title-%>
<%- if k.titleref then -%></a><%- end -%>
</th>
<%- count = count + 1; end; end; if self.sortable then -%>
<th class="th cbi-section-table-cell"><%:Sort%></th>
<%- end; if self.extedit or self.addremove then -%>
<th class="th cbi-section-table-cell"><%:Edit%></th>
<%- count = count + 1; end -%>
</tr>
<tr class="tr cbi-section-table-descr">
<%- if not self.anonymous then -%>
<%- if self.sectiondesc then -%>
<th class="th cbi-section-table-cell"><%=self.sectiondesc%></th>
<%- else -%>
<th class="th cbi-section-table-cell"></th>
<%- end -%>
<%- end -%>
<%- for i, k in pairs(self.children) do if not k.optional then -%>
<%- if i == 1 then -%>
<th class="th cbi-section-table-cell"></th>
<%- end -%>
<th class="th cbi-section-table-cell"<%=width(k)%>><%=k.description%></th>
<%- end; end; if self.sortable then -%>
<th class="th cbi-section-table-cell"></th>
<%- end; if self.extedit or self.addremove then -%>
<th class="th cbi-section-table-cell"></th>
<%- end -%>
</tr>
<%- local isempty = true
local num = 1
for i, k in ipairs(self:cfgsections()) do
local section = k
local should_render = false
local section_name
if self.sectiontype == "dns_servers" then
section_name = uci:get("openclash", section, "group")
else
section_name = uci:get("openclash", section, "config")
end
if section_name == tab.name then
should_render = true
end
if should_render then
isempty = false
scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" }
-%>
<tr class="tr cbi-section-table-row<% if self.extedit or self.rowcolors then %> cbi-rowstyle-<%=rowstyle()%><% end %>" id="cbi-<%=self.config%>-<%=section%>">
<%- if not self.anonymous then -%>
<th><h3><%=(type(self.sectiontitle) == "function") and self:sectiontitle(section) or k%></h3></th>
<%- end -%>
<td class="td cbi-section-table-cell">
<p><%=num%></p>
<%- num = num + 1 -%>
</td>
<%-
for k, node in ipairs(self.children) do
if not node.optional then
node:render(section, scope or {})
end
end
-%>
<%- if self.sortable then -%>
<td class="tdcbi-section-table-cell">
<input class="cbi-button cbi-button-up" type="button" value="<%:∧%>" onclick="return cbi_row_swap(this, true, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" alt="<%:Move up%>" title="<%:Move up%>" />
<input class="cbi-button cbi-button-down" type="button" value="<%:∨%>" onclick="return cbi_row_swap(this, false, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" alt="<%:Move down%>" title="<%:Move down%>" />
</td>
<%- end -%>
<%- if self.extedit or self.addremove then -%>
<td class="td cbi-section-table-cell">
<%- if self.extedit then -%>
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>"
<%- if type(self.extedit) == "string" then
%> onclick="location.href='<%=self.extedit:format(section)%>';return switch_to_tab<%=sectiontype%>()"
<%- elseif type(self.extedit) == "function" then
%> onclick="location.href='<%=self:extedit(section)%>';return switch_to_tab<%=sectiontype%>()"
<%- end
%> alt="<%:Edit%>" title="<%:Edit%>" />
<%- end; if self.addremove then -%>
<input class="btn cbi-button cbi-button-remove" type="submit" value="<%:Delete%>" onclick="this.form.cbi_state='del-section'; return switch_to_tab<%=sectiontype%>()" name="cbi.rts.<%=self.config%>.<%=k%>" alt="<%:Delete%>" title="<%:Delete%>" />
<%- end -%>
</td>
<%- end -%>
<%-
end
-%>
</tr>
<%- end -%>
<%- if isempty then -%>
<tr class="tr cbi-section-table-row placeholder">
<td class="td" colspan="<%=count%>"><em><%:This section contains no values yet%></em></td>
</tr>
<%- end -%>
</table>
<%- if self.error then -%>
<div class="cbi-section-error">
<ul><%- for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
<li><%=pcdata(e):gsub("\n","<br />")%></li>
<%- end end -%></ul>
</div>
<%- end -%>
<%- if self.addremove then -%>
<%- if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create cbi-tblsection-create">
<%- if self.anonymous then -%>
<input class="btn cbi-button cbi-button-add" type="submit" onclick="return switch_to_tab<%=sectiontype%>('<%=tab.name%>')" value="<%:Add%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
<%- else -%>
<% if self.invalid_cts then -%><div class="cbi-section-error"><% end %>
<input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname" data-optional="true" />
<input type="submit" class="cbi-button cbi-button-add" onclick="this.form.cbi_state='add-section'; return switch_to_tab<%=sectiontype%>('<%=tab.name%>')" value="<%:Add%>" />
<% if self.invalid_cts then -%>
<br /><%:Invalid%></div>
<%- end %>
<%- end %>
</div>
<%- end -%>
<%- end -%>
</div>
<%- end -%>
<%- if self.addremove then -%>
<input type="hidden" id="cbi.cts.tagname.<%=self.config%>.<%=self.sectiontype%>" name="cbi.cts.tagname.<%=self.config%>.<%=self.sectiontype%>" value="" />
<%- end -%>
</div>
</fieldset>
<!-- /tblsection -->
<script type="text/javascript">//<![CDATA[
window.addEventListener('load', onload<%=sectiontype%>, false);
var titles<%=sectiontype%> = document.getElementsByName('tab-header-<%=self.config%>-<%=self.sectiontype%>');
var divs<%=sectiontype%> = document.getElementsByClassName('dom-<%=self.config%>-<%=self.sectiontype%>');
function isDarkBackground(element) {
var cachedTheme = localStorage.getItem('oc-theme');
if (cachedTheme === 'dark') {
return true;
} else if (cachedTheme === 'light') {
return false;
}
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return true;
}
var style = window.getComputedStyle(element);
var bgColor = style.backgroundColor;
let r, g, b;
if (/rgb\(/.test(bgColor)) {
var rgb = bgColor.match(/\d+/g);
r = parseInt(rgb);
g = parseInt(rgb);
b = parseInt(rgb);
} else if (/#/.test(bgColor)) {
if (bgColor.length === 4) {
r = parseInt(bgColor + bgColor, 16);
g = parseInt(bgColor + bgColor, 16);
b = parseInt(bgColor + bgColor, 16);
} else {
r = parseInt(bgColor.slice(1, 3), 16);
g = parseInt(bgColor.slice(3, 5), 16);
b = parseInt(bgColor.slice(5, 7), 16);
}
} else {
return false;
}
var luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
return luminance < 128;
};
function switch_to_tab<%=sectiontype%>(tab_name){
if(titles<%=sectiontype%>.length != divs<%=sectiontype%>.length) return;
for(var j=0; j < titles<%=sectiontype%>.length; j++){
if(titles<%=sectiontype%>[j].className === 'cbi-tab'){
localStorage.setItem("titles<%=sectiontype%>", j);
break;
}
}
if (tab_name) {
var name = document.getElementById('cbi.cts.tagname.<%=self.config%>.<%=self.sectiontype%>');
if (name) {
name.value = tab_name;
}
}
localStorage.setItem("id<%=sectiontype%>",'cbi-<%=self.config%>-<%=self.sectiontype%>');
return true;
};
function onload<%=sectiontype%>() {
if (isDarkBackground(document.body)) {
document.documentElement.setAttribute('data-darkmode', 'true');
};
if(titles<%=sectiontype%>.length != divs<%=sectiontype%>.length) return;
if (localStorage.getItem("id<%=sectiontype%>")) {
if (document.getElementById(localStorage.getItem("id<%=sectiontype%>"))) {
document.getElementById(localStorage.getItem("id<%=sectiontype%>")).scrollIntoView();
};
localStorage.removeItem("id<%=sectiontype%>");
};
if (localStorage.getItem("titles<%=sectiontype%>")) {
if (titles<%=sectiontype%>[localStorage.getItem("titles<%=sectiontype%>")]) {
for(var j=0; j < titles<%=sectiontype%>.length; j++){
titles<%=sectiontype%>[j].className = 'cbi-tab-disabled';
divs<%=sectiontype%>[j].style.display = 'none';
};
titles<%=sectiontype%>[localStorage.getItem("titles<%=sectiontype%>")].className = 'cbi-tab';
divs<%=sectiontype%>[localStorage.getItem("titles<%=sectiontype%>")].style.display = 'block';
};
localStorage.removeItem("titles<%=sectiontype%>");
};
for(var i=0; i < titles<%=sectiontype%>.length; i++){
var li<%=sectiontype%> = titles<%=sectiontype%>[i];
li<%=sectiontype%>.id = i;
var a<%=sectiontype%> = li<%=sectiontype%>.querySelector('a');
if (a<%=sectiontype%>) {
if (a<%=sectiontype%>.scrollWidth > a<%=sectiontype%>.clientWidth) {
a<%=sectiontype%>.style.textAlign = 'left';
} else {
a<%=sectiontype%>.style.textAlign = 'center';
}
}
li<%=sectiontype%>.onclick = function(){
for(var j=0; j < titles<%=sectiontype%>.length; j++){
titles<%=sectiontype%>[j].className = 'cbi-tab-disabled';
divs<%=sectiontype%>[j].style.display = 'none';
};
this.className = 'cbi-tab';
divs<%=sectiontype%>[this.id].style.display = 'block';
localStorage.setItem("titles<%=sectiontype%>",this.id);
};
li<%=sectiontype%>.onTouchStart = function(){
for(var j=0; j < titles<%=sectiontype%>.length; j++){
titles<%=sectiontype%>[j].className = 'cbi-tab-disabled';
divs<%=sectiontype%>[j].style.display = 'none';
};
this.className = 'cbi-tab';
divs<%=sectiontype%>[this.id].style.display = 'block';
localStorage.setItem("titles<%=sectiontype%>",this.id);
};
};
};
//]]>
</script>