small-packages/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_table.htm
2026-07-17 01:09:25 +08:00

364 lines
10 KiB
HTML

<%-
local rowcnt = 0
function rowstyle()
rowcnt = rowcnt + 1
if rowcnt % 2 == 0 then
return " cbi-rowstyle-1"
else
return " cbi-rowstyle-2"
end
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
local has_titles = false
local has_descriptions = false
local anonclass = (not self.anonymous or self.sectiontitle) and "named" or "anonymous"
local titlename = ifattr(not self.anonymous or self.sectiontitle, "data-title", translate("Name"))
local i, k
for i, k in pairs(self.children) do
if not k.typename then
k.typename = k.template and k.template:gsub("^.+/", "") or ""
end
if not has_titles and k.title and #k.title > 0 then
has_titles = true
end
if not has_descriptions and k.description and #k.description > 0 then
has_descriptions = true
end
end
local total = tonumber(self.server_total) or 0
local page = tonumber(self.server_page) or 1
local page_size = tonumber(self.server_page_size) or 0
local page_count = tonumber(self.server_page_count) or 1
local first_index = tonumber(self.server_first_index) or 0
local last_index = tonumber(self.server_last_index) or 0
local page_sizes = self.server_page_sizes or {}
local base_url = self.server_base_url or ""
local function page_url(target_page, target_size)
return string.format(
"%s?server_page=%d&server_page_size=%d",
base_url,
target_page,
target_size
)
end
function render_titles()
if not has_titles then
return
end
%><tr class="tr cbi-section-table-titles <%=anonclass%>"<%=titlename%>><%
local i, k
for i, k in ipairs(self.children) do
if not k.optional then
%><th class="th cbi-section-table-cell"<%=
width(k) .. attr("data-widget", k.typename) %>><%
if k.titleref then
%><a title="<%=self.titledesc or translate("Go to relevant configuration page")%>" class="cbi-title-ref" href="<%=k.titleref%>"><%
end
write(k.title)
if k.titleref then
%></a><%
end
%></th><%
end
end
if self.sortable or self.extedit or self.addremove then
%><th class="th cbi-section-table-cell cbi-section-actions"></th><%
end
%></tr><%
rowcnt = rowcnt + 1
end
function render_descriptions()
if not has_descriptions then
return
end
%><tr class="tr cbi-section-table-descr <%=anonclass%>"><%
local i, k
for i, k in ipairs(self.children) do
if not k.optional then
%><th class="th cbi-section-table-cell"<%=
width(k) .. attr("data-widget", k.typename) %>><%
write(k.description)
%></th><%
end
end
if self.sortable or self.extedit or self.addremove then
%><th class="th cbi-section-table-cell cbi-section-actions"></th><%
end
%></tr><%
rowcnt = rowcnt + 1
end
function render_pager()
if total == 0 then
return
end
%>
<div class="ssr-server-pager">
<span class="ssr-server-pager-summary">
<%=string.format(translate("Showing %d-%d of %d nodes"), first_index, last_index, total)%>
</span>
<span class="ssr-server-pager-pages">
<% if page_count > 1 then %>
<% if page > 1 then %>
<a class="cbi-button cbi-button-link" href="<%=page_url(page - 1, page_size)%>"><%:Prev%></a>
<% end %>
<% for current = 1, page_count do %>
<% if current == page then %>
<strong><%=current%></strong>
<% else %>
<a class="cbi-button cbi-button-link" href="<%=page_url(current, page_size)%>"><%=current%></a>
<% end %>
<% end %>
<% if page < page_count then %>
<a class="cbi-button cbi-button-link" href="<%=page_url(page + 1, page_size)%>"><%:Next%></a>
<% end %>
<% end %>
</span>
<span class="ssr-server-pager-sizes">
<%:Per page%>:
<% for _, size in ipairs(page_sizes) do %>
<%
local label = size == 0 and translate("All") or tostring(size)
local selected = size == page_size
%>
<% if selected then %>
<strong><%=label%></strong>
<% else %>
<a class="cbi-button cbi-button-link" href="<%=page_url(1, size)%>"><%=label%></a>
<% end %>
<% end %>
</span>
</div>
<input type="hidden" id="cbi-server-page" value="<%=page%>" />
<input type="hidden" id="cbi-server-page-size" value="<%=page_size%>" />
<%
end
-%>
<style type="text/css">
.ssr-server-pager {
display: flex;
flex-wrap: wrap;
gap: 0.5rem 0.75rem;
align-items: center;
margin: 0.5rem 0 0.75rem;
}
.ssr-server-pager-pages,
.ssr-server-pager-sizes {
display: inline-flex;
flex-wrap: wrap;
align-items: center;
gap: 0.35rem;
}
.ssr-server-pager .cbi-button-link {
padding: 0 0.45rem;
min-width: 1.75rem;
text-align: center;
}
</style>
<!-- tblsection -->
<div class="cbi-section cbi-tblsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<script type="text/javascript">
if (!window.ssrXHR) {
window.ssrXHR = (function() {
function encode(data) {
var pairs = [];
var key;
for (key in (data || {})) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key] == null ? '' : data[key]));
}
}
return pairs.join('&');
}
function request(method, url, data, callback) {
var lower = method.toLowerCase();
if (window.XHR && typeof window.XHR[lower] === "function") {
return window.XHR[lower](url, data, callback);
}
var xhr = new XMLHttpRequest();
var payload = encode(data);
var finalUrl = url;
if (lower === "get" && payload) {
finalUrl += (url.indexOf('?') === -1 ? '?' : '&') + payload;
}
xhr.open(method, finalUrl, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
if (lower !== "get") {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
}
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
var rv = null;
try {
rv = JSON.parse(xhr.responseText || 'null');
} catch (e) {}
if (callback) callback(xhr, rv);
};
xhr.send(lower === "get" ? null : payload);
}
return {
get: function(url, data, callback) {
return request('GET', url, data, callback);
},
post: function(url, data, callback) {
return request('POST', url, data, callback);
}
};
})();
}
if (typeof window.ssrDeleteNode !== "function") {
window.ssrDeleteNode = function(sid) {
window.ssrXHR.post('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "delete_node")%>', {
sid: sid
}, function(x, result) {
result = result || {};
if (result.ret == 1) {
window.location.reload();
}
});
return false;
};
}
</script>
<% 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>
<% render_pager() %>
<table class="table cbi-section-table">
<%-
render_titles()
render_descriptions()
local isempty, section, i, k = true, nil, nil
for i, k in ipairs(self:cfgsections()) do
isempty = false
section = k
local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname, true)
local colorclass = (self.extedit or self.rowcolors) and rowstyle() or ""
local scope = {
valueheader = "cbi/cell_valueheader",
valuefooter = "cbi/cell_valuefooter"
}
-%>
<tr class="tr cbi-section-table-row<%=colorclass%>" id="cbi-<%=self.config%>-<%=section%>"<%=sectiontitle%>>
<%-
local node
for k, node in ipairs(self.children) do
if not node.optional then
node:render(section, scope or {})
end
end
-%>
<%- if self.sortable or self.extedit or self.addremove then -%>
<td class="td cbi-section-table-cell nowrap cbi-section-actions">
<div>
<% 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)%>'"
<%- elseif type(self.extedit) == "function" then
%> onclick="location.href='<%=self:extedit(section)%>'"
<%- end
%> alt="<%:Edit%>" title="<%:Edit%>" />
<% end; if self.addremove then %>
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Delete%>"
onclick="return window.ssrDeleteNode('<%=k%>')"
/>
<%- end -%>
</div>
</td>
<%- end -%>
</tr>
<%- end -%>
<%- if isempty then -%>
<tr class="tr cbi-section-table-row placeholder">
<td class="td"><em><%:This section contains no values yet%></em></td>
</tr>
<%- end -%>
</table>
<% render_pager() %>
<% 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" value="<%:Add%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
<% else %>
<% if self.invalid_cts then -%>
<div class="cbi-section-error"><%:Invalid%></div>
<%- end %>
<div>
<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" onkeyup="cbi_validate_named_section_add(this)" />
</div>
<input class="btn cbi-button cbi-button-add" type="submit" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" title="<%:Add%>" disabled="" />
<% end %>
</div>
<%- end %>
<%- end -%>
</div>
<!-- /tblsection -->