update 2024-08-25 15:41:13
201
luci-theme-design/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
14
luci-theme-design/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Design Theme
|
||||
LUCI_DEPENDS:=
|
||||
PKG_VERSION:=5.8.0-20240106
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
107
luci-theme-design/README.md
Normal file
@ -0,0 +1,107 @@
|
||||
<div align="center">
|
||||
<h1 align="center">
|
||||
LuCI design theme for OpenWrt
|
||||
</h1>
|
||||
<a href="/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/gngpp/luci-theme-design?style=flat&a=1" alt="">
|
||||
</a>
|
||||
<a href="https://github.com/gngpp/luci-theme-design/pulls">
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="">
|
||||
</a><a href="https://github.com/gngpp/luci-theme-design/issues/new">
|
||||
<img src="https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat">
|
||||
</a><a href="https://github.com/gngpp/luci-theme-design/releases">
|
||||
<img src="https://img.shields.io/github/release/gngpp/luci-theme-design.svg?style=flat">
|
||||
</a><a href="hhttps://github.com/gngpp/luci-theme-design/releases">
|
||||
<img src="https://img.shields.io/github/downloads/gngpp/luci-theme-design/total?style=flat&?">
|
||||
</a>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<br>简体中文 | [English](README_en.md)
|
||||
|
||||
# luci-theme-design
|
||||
|
||||
luci-theme-design 是一个针对移动端和PC端的沉浸式WebApp体验和优化的OpenWrt LuCI主题
|
||||
- **luci-theme-design**基于luci-theme-neobird二次开发, 适用于[lede](https://github.com/coolsnowwolf/lede)
|
||||
- main支持lede源码的lua版本
|
||||
- js分支开始由[papagaye744](https://github.com/papagaye744)维护
|
||||
|
||||
- 你可以使用[插件](https://github.com/gngpp/luci-app-design-config)定义一些设置
|
||||
- 支持更改主题深色/浅色模式
|
||||
- 支持显示/隐藏导航栏
|
||||
- 支持更换常用的代理图标
|
||||
|
||||
- 感谢 [JetBrains](https://www.jetbrains.com/) 提供的非商业开源软件开发授权!
|
||||
<a href="https://www.jetbrains.com/?from=gnet" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||
|
||||
### 主要特点
|
||||
|
||||
- 适配移动端响应式优化,适合手机端做为WebApp使用
|
||||
- 修改和优化了很多插件显示,完善的设备icon图标,视觉统一
|
||||
- 简洁的登录界面,底部导航栏,类App的沉浸式体验
|
||||
- 适配深色模式,适配系统自动切换,插件式自定义模式
|
||||
- 支持插件式配置主题
|
||||
- 流畅度比肩bootstrap
|
||||
|
||||
### 体验WebApp方法
|
||||
|
||||
- 在移动端(iOS/iPadOS、Android谷歌)浏览器打开设置管理,添加到主屏幕即可。
|
||||
|
||||
### 优化
|
||||
|
||||
- 修复安装package提示信息背景泛白
|
||||
- 优化菜单折叠和缩放
|
||||
- 优化显示网口down状态显示图标
|
||||
- 优化logo显示
|
||||
- 新增各设备状态图标显示
|
||||
- 更换logo显示为字体"OpenWrt",支持以主机名显示logo
|
||||
- 修复部分插件显示bug
|
||||
- 修复vssr状态bar
|
||||
- 修复诸多bug
|
||||
- 修复兼容部分插件样式
|
||||
- 修复aliyundrive-webdav样式
|
||||
- 修复vssr在iOS/iPadOS WebApp模式下显示异常
|
||||
- 修复openclash插件在iOS/iPadOS WebApp 模式下env(safe-area-inset-bottom) = 0
|
||||
- 优化菜单hover action状态分辨
|
||||
- 支持luci-app-wizard向导菜单
|
||||
- Update header box-shadow style
|
||||
- Update uci-change overflow
|
||||
- Fix nlbw component
|
||||
- 支持QWRT(QSDK)、iStore向导导航
|
||||
- 适配OpenWrt 21/22
|
||||
...
|
||||
|
||||
### 编译
|
||||
|
||||
```
|
||||
git clone https://github.com/kenzok78/luci-theme-design.git package/luci-theme-design
|
||||
make menuconfig # choose LUCI->Theme->Luci-theme-design
|
||||
make V=s
|
||||
```
|
||||
|
||||
### Q&A
|
||||
|
||||
- 有bug欢迎提issue
|
||||
- 主题个人配色可能会不符合大众胃口,欢迎提配色建议
|
||||
|
||||
### 预览
|
||||
|
||||
<details> <summary>iOS</summary>
|
||||
<img src="./preview/webapp_home.PNG"/>
|
||||
<img src="./preview/webapp_vssr.PNG"/>
|
||||
</details>
|
||||
|
||||
<details> <summary>iPadOS</summary>
|
||||
<img src="./preview/IMG_0328.PNG"/>
|
||||
<img src="./preview/IMG_0329.PNG"/>
|
||||
</details>
|
||||
|
||||
<img src="./preview/login.png"/>
|
||||
<img src="./preview/login1.png"/>
|
||||
<img src="./preview/page.png"/>
|
||||
<img src="./preview/home.png"/>
|
||||
<img src="./preview/light.png"/>
|
||||
<img src="./preview/home1.png"/>
|
||||
<img src="./preview/wifi.png"/>
|
||||
<img src="./preview/iface.png"/>
|
||||
<img src="./preview/firewall.png"/>
|
98
luci-theme-design/README_en.md
Normal file
@ -0,0 +1,98 @@
|
||||
<div align="center">
|
||||
<h1 align="center">
|
||||
LuCI design theme for OpenWrt
|
||||
</h1>
|
||||
<a href="/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/gngpp/luci-theme-design?style=flat&a=1" alt="">
|
||||
</a>
|
||||
<a href="https://github.com/gngpp/luci-theme-design/pulls">
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="">
|
||||
</a><a href="https://github.com/gngpp/luci-theme-design/issues/new">
|
||||
<img src="https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat">
|
||||
</a><a href="https://github.com/gngpp/luci-theme-design/releases">
|
||||
<img src="https://img.shields.io/github/release/gngpp/luci-theme-design.svg?style=flat">
|
||||
</a><a href="hhttps://github.com/gngpp/luci-theme-design/releases">
|
||||
<img src="https://img.shields.io/github/downloads/gngpp/luci-theme-design/total?style=flat">
|
||||
</a>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<br>English | [简体中文](README.md)
|
||||
|
||||
# luci-theme-design
|
||||
|
||||
### luci-theme-design is an OpenWrt LuCI theme for immersive WebApp experience and optimization on mobile and PC
|
||||
- **luci-theme-design** based on luci-theme-neobird, for [lede](https://github.com/coolsnowwolf/lede) / [OpenWrt](https://github.com/openwrt/ openwrt)
|
||||
- The default branch only supports the lua version of the lede source code. If you use openwrt 21/22, please pull the [js](https://github.com/gngpp/luci-theme-design/tree/js) version (development stage).
|
||||
|
||||
- You can define some settings using [plugin](https://github.com/gngpp/luci-app-design-config)
|
||||
- Support changing theme dark/light mode
|
||||
- Support show/hide navigation bar
|
||||
- Support replacing commonly used proxy icons
|
||||
|
||||
### If you find it useful, please click a star, your support is the driving force for my long-term updates, thank you.
|
||||
|
||||
- Thanks for non-commercial open source development authorization by [JetBrains](https://www.jetbrains.com/)!
|
||||
<a href="https://www.jetbrains.com/?from=gnet" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||
|
||||
### Release version
|
||||
|
||||
- Lua version select 5.x version
|
||||
- JS version select 6.x version
|
||||
|
||||
### Features
|
||||
|
||||
- Adapt to the responsive optimization of the mobile terminal, suitable for use as a WebApp on the mobile terminal
|
||||
- Modified and optimized the display of many plug-ins, improved icon icons, and unified visuals as much as possible
|
||||
- Simple login interface, bottom navigation bar, immersive app-like experience
|
||||
- Adapt to dark mode, adapt to system automatic switching, support custom mode
|
||||
- Adapt to openwrt 21/22, lede
|
||||
|
||||
### Experience WebApp method
|
||||
|
||||
- Open the settings management in the mobile browser (iOS/iPadOS, Android Google) and add it to the home screen.
|
||||
- If the SSL certificate is not used, iOS/iPadOS will display the menu bar at the top of the browser after opening a new page for security reasons.
|
||||
|
||||
### Optimization
|
||||
|
||||
- Optimize menu collapsing and zooming
|
||||
- Optimized to display network port down state display icon
|
||||
- Support QWRT (QSDK), iStore wizard navigation
|
||||
- Adapt to OpenWrt 21/22
|
||||
- Adapt to linkease series icons
|
||||
|
||||
### Compile
|
||||
|
||||
```
|
||||
git clone https://github.com/gngpp/luci-theme-design.git package/luci-theme-design
|
||||
make menuconfig # choose LUCI->Theme->Luci-theme-design
|
||||
make V=s
|
||||
```
|
||||
|
||||
### Q&A
|
||||
|
||||
- The resource interface icon is not perfect. If you have the ability to draw a picture, you are welcome to pr, but please make sure it is consistent with the existing icon color style
|
||||
- If there is a bug, please raise an issue
|
||||
- The theme's personal color matching may not meet the public's appetite, welcome to provide color matching suggestions
|
||||
|
||||
### Preview
|
||||
|
||||
<details> <summary>iOS</summary>
|
||||
<img src="./preview/webapp_home.PNG"/>
|
||||
<img src="./preview/webapp_vssr.PNG"/>
|
||||
</details>
|
||||
|
||||
<details> <summary>iPadOS</summary>
|
||||
<img src="./preview/IMG_0328.PNG"/>
|
||||
<img src="./preview/IMG_0329.PNG"/>
|
||||
</details>
|
||||
|
||||
<img src="./preview/login.png"/>
|
||||
<img src="./preview/login1.png"/>
|
||||
<img src="./preview/page.png"/>
|
||||
<img src="./preview/home.png"/>
|
||||
<img src="./preview/light.png"/>
|
||||
<img src="./preview/home1.png"/>
|
||||
<img src="./preview/wifi.png"/>
|
||||
<img src="./preview/iface.png"/>
|
||||
<img src="./preview/firewall.png"/>
|
266
luci-theme-design/dev/design.js
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* xhr.js - XMLHttpRequest helper class
|
||||
* (c) 2008-2010 Jo-Philipp Wich
|
||||
*/
|
||||
|
||||
XHR = function()
|
||||
{
|
||||
this.reinit = function()
|
||||
{
|
||||
if (window.XMLHttpRequest) {
|
||||
this._xmlHttp = new XMLHttpRequest();
|
||||
}
|
||||
else if (window.ActiveXObject) {
|
||||
this._xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
else {
|
||||
alert("xhr.js: XMLHttpRequest is not supported by this browser!");
|
||||
}
|
||||
}
|
||||
|
||||
this.busy = function() {
|
||||
if (!this._xmlHttp)
|
||||
return false;
|
||||
|
||||
switch (this._xmlHttp.readyState)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.abort = function() {
|
||||
if (this.busy())
|
||||
this._xmlHttp.abort();
|
||||
}
|
||||
|
||||
this.get = function(url,data,callback)
|
||||
{
|
||||
this.reinit();
|
||||
|
||||
var xhr = this._xmlHttp;
|
||||
var code = this._encode(data);
|
||||
|
||||
url = location.protocol + '//' + location.host + url;
|
||||
|
||||
if (code)
|
||||
if (url.substr(url.length-1,1) == '&')
|
||||
url += code;
|
||||
else
|
||||
url += '?' + code;
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
|
||||
xhr.onreadystatechange = function()
|
||||
{
|
||||
if (xhr.readyState == 4) {
|
||||
var json = null;
|
||||
if (xhr.getResponseHeader("Content-Type") == "application/json") {
|
||||
try {
|
||||
json = eval('(' + xhr.responseText + ')');
|
||||
}
|
||||
catch(e) {
|
||||
json = null;
|
||||
}
|
||||
}
|
||||
|
||||
callback(xhr, json);
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
this.post = function(url,data,callback)
|
||||
{
|
||||
this.reinit();
|
||||
|
||||
var xhr = this._xmlHttp;
|
||||
var code = this._encode(data);
|
||||
|
||||
xhr.onreadystatechange = function()
|
||||
{
|
||||
if (xhr.readyState == 4)
|
||||
callback(xhr);
|
||||
}
|
||||
|
||||
xhr.open('POST', url, true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr.send(code);
|
||||
}
|
||||
|
||||
this.cancel = function()
|
||||
{
|
||||
this._xmlHttp.onreadystatechange = function(){};
|
||||
this._xmlHttp.abort();
|
||||
}
|
||||
|
||||
this.send_form = function(form,callback,extra_values)
|
||||
{
|
||||
var code = '';
|
||||
|
||||
for (var i = 0; i < form.elements.length; i++)
|
||||
{
|
||||
var e = form.elements[i];
|
||||
|
||||
if (e.options)
|
||||
{
|
||||
code += (code ? '&' : '') +
|
||||
form.elements[i].name + '=' + encodeURIComponent(
|
||||
e.options[e.selectedIndex].value
|
||||
);
|
||||
}
|
||||
else if (e.length)
|
||||
{
|
||||
for (var j = 0; j < e.length; j++)
|
||||
if (e[j].name) {
|
||||
code += (code ? '&' : '') +
|
||||
e[j].name + '=' + encodeURIComponent(e[j].value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
code += (code ? '&' : '') +
|
||||
e.name + '=' + encodeURIComponent(e.value);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof extra_values == 'object')
|
||||
for (var key in extra_values)
|
||||
code += (code ? '&' : '') +
|
||||
key + '=' + encodeURIComponent(extra_values[key]);
|
||||
|
||||
return(
|
||||
(form.method == 'get')
|
||||
? this.get(form.getAttribute('action'), code, callback)
|
||||
: this.post(form.getAttribute('action'), code, callback)
|
||||
);
|
||||
}
|
||||
|
||||
this._encode = function(obj)
|
||||
{
|
||||
obj = obj ? obj : { };
|
||||
obj['_'] = Math.random();
|
||||
|
||||
if (typeof obj == 'object')
|
||||
{
|
||||
var code = '';
|
||||
var self = this;
|
||||
|
||||
for (var k in obj)
|
||||
code += (code ? '&' : '') +
|
||||
k + '=' + encodeURIComponent(obj[k]);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
XHR.get = function(url, data, callback)
|
||||
{
|
||||
(new XHR()).get(url, data, callback);
|
||||
}
|
||||
|
||||
XHR.poll = function(interval, url, data, callback)
|
||||
{
|
||||
if (isNaN(interval) || interval < 1)
|
||||
interval = 5;
|
||||
|
||||
if (!XHR._q)
|
||||
{
|
||||
XHR._t = 0;
|
||||
XHR._q = [ ];
|
||||
XHR._r = function() {
|
||||
for (var i = 0, e = XHR._q[0]; i < XHR._q.length; e = XHR._q[++i])
|
||||
{
|
||||
if (!(XHR._t % e.interval) && !e.xhr.busy())
|
||||
e.xhr.get(e.url, e.data, e.callback);
|
||||
}
|
||||
|
||||
XHR._t++;
|
||||
};
|
||||
}
|
||||
|
||||
XHR._q.push({
|
||||
interval: interval,
|
||||
callback: callback,
|
||||
url: url,
|
||||
data: data,
|
||||
xhr: new XHR()
|
||||
});
|
||||
|
||||
XHR.run();
|
||||
}
|
||||
|
||||
XHR.halt = function()
|
||||
{
|
||||
if (XHR._i)
|
||||
{
|
||||
/* show & set poll indicator */
|
||||
try {
|
||||
document.getElementById('xhr_poll_status').style.display = '';
|
||||
document.getElementById('xhr_poll_status_on').style.display = 'none';
|
||||
document.getElementById('xhr_poll_status_off').style.display = '';
|
||||
document.getElementById('notice_status').style.marginRight = '30px'
|
||||
} catch(e) { }
|
||||
|
||||
window.clearInterval(XHR._i);
|
||||
XHR._i = null;
|
||||
}
|
||||
}
|
||||
|
||||
XHR.run = function()
|
||||
{
|
||||
if (XHR._r && !XHR._i)
|
||||
{
|
||||
/* show & set poll indicator */
|
||||
try {
|
||||
document.getElementById('xhr_poll_status').style.display = '';
|
||||
document.getElementById('xhr_poll_status_on').style.display = '';
|
||||
document.getElementById('xhr_poll_status_off').style.display = 'none';
|
||||
document.getElementById('notice_status').style.marginRight = '30px'
|
||||
} catch(e) { }
|
||||
|
||||
/* kick first round manually to prevent one second lag when setting up
|
||||
* the poll interval */
|
||||
XHR._r();
|
||||
XHR._i = window.setInterval(XHR._r, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
XHR.running = function()
|
||||
{
|
||||
return !!(XHR._r && XHR._i);
|
||||
}
|
||||
|
||||
;(function ($) {
|
||||
// Fixed status realtime table overflow style
|
||||
function settingsStatusRealtimeOverflow() {
|
||||
if (self.location.pathname.includes("status/realtime")) {
|
||||
const nodeStatusRealtime = $('.node-status-realtime');
|
||||
const selectorValues = ['bandwidth', 'wifirate', 'wireless'];
|
||||
// .node-status-realtime embed[src="/luci-static/resources/bandwidth.svg"] + div + br + table
|
||||
// .node-status-realtime embed[src="/luci-static/resources/wifirate.svg"] + div + br + table
|
||||
// .node-status-realtime embed[src="/luci-static/resources/wireless.svg"] + div + br + table
|
||||
for (let i = 0; i < selectorValues.length; i++) {
|
||||
const value = selectorValues[i];
|
||||
const target = nodeStatusRealtime.find(`embed[src="/luci-static/resources/${value}.svg"] + div + br + table`);
|
||||
if (target.length) {
|
||||
target.wrap('<div style="overflow-x: auto;"></div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
settingsStatusRealtimeOverflow();
|
||||
});
|
||||
|
||||
})(jQuery);
|
247
luci-theme-design/dev/script.js
Normal file
@ -0,0 +1,247 @@
|
||||
/**
|
||||
* Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
|
||||
*
|
||||
* luci-theme-argon
|
||||
* Copyright 2023 gngpp <gngppz@gmail.com>
|
||||
*
|
||||
* Have a bug? Please create an issue here on GitHub!
|
||||
* https://github.com/LuttyYang/luci-theme-material/issues
|
||||
*
|
||||
* luci-theme-bootstrap:
|
||||
* Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
* Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
* Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
*
|
||||
* MUI:
|
||||
* https://github.com/muicss/mui
|
||||
*
|
||||
* luci-theme-material:
|
||||
* https://github.com/LuttyYang/luci-theme-material/
|
||||
*
|
||||
*
|
||||
* Licensed to the public under the Apache License 2.0
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
$(".main > .loading").fadeOut();
|
||||
|
||||
/**
|
||||
* trim text, Remove spaces, wrap
|
||||
* @param text
|
||||
* @returns {string}
|
||||
*/
|
||||
function trimText(text) {
|
||||
return text.replace(/[ \t\n\r]+/g, " ");
|
||||
}
|
||||
|
||||
var lastNode = undefined;
|
||||
var mainNodeName = undefined;
|
||||
|
||||
var nodeUrl = "";
|
||||
(function (node) {
|
||||
if (node[0] == "admin") {
|
||||
luciLocation = [node[1], node[2]];
|
||||
} else {
|
||||
luciLocation = node;
|
||||
}
|
||||
|
||||
for (var i in luciLocation) {
|
||||
nodeUrl += luciLocation[i];
|
||||
if (i != luciLocation.length - 1) {
|
||||
nodeUrl += "/";
|
||||
}
|
||||
}
|
||||
})(luciLocation);
|
||||
|
||||
/**
|
||||
* get the current node by Burl (primary)
|
||||
* @returns {boolean} success?
|
||||
*/
|
||||
function getCurrentNodeByUrl() {
|
||||
if (!$('body').hasClass('logged-in')) {
|
||||
luciLocation = ["Main", "Login"];
|
||||
return true;
|
||||
}
|
||||
const urlReg = new RegExp(nodeUrl + "$")
|
||||
var ret = false;
|
||||
$(".main > .main-left > .nav > .slide > .active").next(".slide-menu").stop(true).slideUp("fast");
|
||||
$(".main > .main-left > .nav > .slide > .menu").removeClass("active");
|
||||
$(".main > .main-left > .nav > .slide > .menu").each(function () {
|
||||
var ulNode = $(this);
|
||||
|
||||
ulNode.next().find("a").each(function () {
|
||||
var that = $(this);
|
||||
var href = that.attr("href");
|
||||
|
||||
if (urlReg.test(href)) {
|
||||
ulNode.click();
|
||||
ulNode.next(".slide-menu").stop(true, true);
|
||||
lastNode = that.parent();
|
||||
lastNode.addClass("active");
|
||||
ret = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .menu").click(function () {
|
||||
var ul = $(this).next(".slide-menu");
|
||||
var menu = $(this);
|
||||
if (!menu.hasClass("exit")) {
|
||||
$(".main > .main-left > .nav > .slide > .active").next(".slide-menu").stop(true).slideUp("fast");
|
||||
$(".main > .main-left > .nav > .slide > .menu").removeClass("active");
|
||||
if (!ul.is(":visible")) {
|
||||
menu.addClass("active");
|
||||
ul.addClass("active");
|
||||
ul.stop(true).slideDown("fast");
|
||||
} else {
|
||||
ul.stop(true).slideUp("fast", function () {
|
||||
menu.removeClass("active");
|
||||
ul.removeClass("active");
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* hook menu click and add the hash
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
|
||||
if (lastNode != undefined)
|
||||
lastNode.removeClass("active");
|
||||
$(this).parent().addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
|
||||
if (lastNode != undefined)
|
||||
lastNode.removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* get current node and open it
|
||||
*/
|
||||
if (getCurrentNodeByUrl()) {
|
||||
mainNodeName = "node-" + luciLocation[0] + "-" + luciLocation[1];
|
||||
mainNodeName = mainNodeName.replace(/[ \t\n\r\/]+/g, "_").toLowerCase();
|
||||
$("body").addClass(mainNodeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* hook other "A Label" and add hash to it.
|
||||
*/
|
||||
$("#maincontent > .container").find("a").each(function () {
|
||||
var that = $(this);
|
||||
var onclick = that.attr("onclick");
|
||||
if (onclick == undefined || onclick == "") {
|
||||
that.click(function () {
|
||||
var href = that.attr("href");
|
||||
if (href.indexOf("#") == -1) {
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sidebar expand
|
||||
*/
|
||||
var showSide = false;
|
||||
|
||||
$(".showSide").click(function () {
|
||||
if (showSide) {
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
$("header>.container>.brand").css("padding", "0 4.5rem")
|
||||
showSide = false;
|
||||
} else {
|
||||
$(".darkMask").stop(true).fadeIn("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "18rem"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "hidden");
|
||||
$(".showSide").css("display", "none");
|
||||
$("header").css("box-shadow", "18rem 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding", '0rem')
|
||||
showSide = true;
|
||||
}
|
||||
});
|
||||
|
||||
$(".darkMask").click(function () {
|
||||
if (showSide) {
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
$(".showSide").css("display", "");
|
||||
$("header").css("box-shadow", "0 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding", "0 4.5rem")
|
||||
showSide = false;
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function () {
|
||||
if ($(window).width() > 992) {
|
||||
showSide = false;
|
||||
$(".showSide").css("display", "");
|
||||
$(".main-left").css("width", "");
|
||||
$(".darkMask").stop(true);
|
||||
$(".darkMask").css("display", "none");
|
||||
$("header").css("box-shadow", "18rem 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding", '0rem')
|
||||
} else {
|
||||
$("header").css("box-shadow", "0 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding", "0 4.5rem")
|
||||
}
|
||||
if (showSide) {
|
||||
$("header").css("box-shadow", "18rem 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding", '0rem')
|
||||
}
|
||||
});
|
||||
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
$("input").attr("size", "0");
|
||||
|
||||
if (mainNodeName != undefined) {
|
||||
switch (mainNodeName) {
|
||||
case "node-status-system_log":
|
||||
case "node-status-kernel_log":
|
||||
$("#syslog").focus(function () {
|
||||
$("#syslog").blur();
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
});
|
||||
break;
|
||||
case "node-status-firewall":
|
||||
var button = $(".node-status-firewall > .main fieldset li > a");
|
||||
button.addClass("cbi-button cbi-button-reset a-to-btn");
|
||||
break;
|
||||
case "node-system-reboot":
|
||||
var button = $(".node-system-reboot > .main > .main-right p > a");
|
||||
button.addClass("cbi-button cbi-input-reset a-to-btn");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
3522
luci-theme-design/dev/style.css
Normal file
BIN
luci-theme-design/htdocs/luci-static/design/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/fonts/font.eot
Normal file
16
luci-theme-design/htdocs/luci-static/design/fonts/font.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="expand_less" d="M512 596.667l256-256-60-60-196 196-196-196-60 60z" />
|
||||
<glyph unicode="" glyph-name="expand_more" d="M708 572.667l60-60-256-256-256 256 60 60 196-196z" />
|
||||
<glyph unicode="" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
|
||||
<glyph unicode="" glyph-name="favorite" d="M512 28.667l-62 56q-106 96-154 142t-107 114-81 123-22 113q0 98 67 166t167 68q116 0 192-90 76 90 192 90 100 0 167-68t67-166q0-78-52-162t-113-146-199-186z" />
|
||||
<glyph unicode="" glyph-name="spinner9" d="M512 960c-278.748 0-505.458-222.762-511.848-499.974 5.92 241.864 189.832 435.974 415.848 435.974 229.75 0 416-200.576 416-448 0-53.020 42.98-96 96-96s96 42.98 96 96c0 282.77-229.23 512-512 512zM512-64c278.748 0 505.458 222.762 511.848 499.974-5.92-241.864-189.832-435.974-415.848-435.974-229.75 0-416 200.576-416 448 0 53.020-42.98 96-96 96s-96-42.98-96-96c0-282.77 229.23-512 512-512z" />
|
||||
<glyph unicode="" glyph-name="question-circle" horiz-adv-x="878" d="M512 164.571v109.714q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-109.714q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM658.286 548.571q0 50.286-31.714 93.143t-79.143 66.286-97.143 23.429q-138.857 0-212-121.714-8.571-13.714 4.571-24l75.429-57.143q4-3.429 10.857-3.429 9.143 0 14.286 6.857 30.286 38.857 49.143 52.571 19.429 13.714 49.143 13.714 27.429 0 48.857-14.857t21.429-33.714q0-21.714-11.429-34.857t-38.857-25.714q-36-16-66-49.429t-30-71.714v-20.571q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143q0 10.857 12.286 28.286t31.143 28.286q18.286 10.286 28 16.286t26.286 20 25.429 27.429 16 34.571 7.143 46.286zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
|
||||
</font></defs></svg>
|
After Width: | Height: | Size: 2.4 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/fonts/font.ttf
Normal file
BIN
luci-theme-design/htdocs/luci-static/design/fonts/font.woff
Normal file
BIN
luci-theme-design/htdocs/luci-static/design/images/add.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 13 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/bridge.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.2 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/ethernet.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/home.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/icon.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/link.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/loading.gif
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/openclash.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/port_down.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/port_up.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/rank.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/reload.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/remove.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.4 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/signal-0.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.0 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/ssr.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/switch.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/tunnel.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/user.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/vlan.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.0 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/wifi.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
luci-theme-design/htdocs/luci-static/design/images/wifi_big.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 15 KiB |
69
luci-theme-design/htdocs/luci-static/design/js/design.js
Normal file
@ -0,0 +1,69 @@
|
||||
XHR=function()
|
||||
{this.reinit=function()
|
||||
{if(window.XMLHttpRequest){this._xmlHttp=new XMLHttpRequest();}
|
||||
else if(window.ActiveXObject){this._xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");}
|
||||
else{alert("xhr.js: XMLHttpRequest is not supported by this browser!");}}
|
||||
this.busy=function(){if(!this._xmlHttp)
|
||||
return false;switch(this._xmlHttp.readyState)
|
||||
{case 1:case 2:case 3:return true;default:return false;}}
|
||||
this.abort=function(){if(this.busy())
|
||||
this._xmlHttp.abort();}
|
||||
this.get=function(url,data,callback)
|
||||
{this.reinit();var xhr=this._xmlHttp;var code=this._encode(data);url=location.protocol+'//'+location.host+url;if(code)
|
||||
if(url.substr(url.length-1,1)=='&')
|
||||
url+=code;else
|
||||
url+='?'+code;xhr.open('GET',url,true);xhr.onreadystatechange=function()
|
||||
{if(xhr.readyState==4){var json=null;if(xhr.getResponseHeader("Content-Type")=="application/json"){try{json=eval('('+xhr.responseText+')');}
|
||||
catch(e){json=null;}}
|
||||
callback(xhr,json);}}
|
||||
xhr.send(null);}
|
||||
this.post=function(url,data,callback)
|
||||
{this.reinit();var xhr=this._xmlHttp;var code=this._encode(data);xhr.onreadystatechange=function()
|
||||
{if(xhr.readyState==4)
|
||||
callback(xhr);}
|
||||
xhr.open('POST',url,true);xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');xhr.send(code);}
|
||||
this.cancel=function()
|
||||
{this._xmlHttp.onreadystatechange=function(){};this._xmlHttp.abort();}
|
||||
this.send_form=function(form,callback,extra_values)
|
||||
{var code='';for(var i=0;i<form.elements.length;i++)
|
||||
{var e=form.elements[i];if(e.options)
|
||||
{code+=(code?'&':'')+
|
||||
form.elements[i].name+'='+encodeURIComponent(e.options[e.selectedIndex].value);}
|
||||
else if(e.length)
|
||||
{for(var j=0;j<e.length;j++)
|
||||
if(e[j].name){code+=(code?'&':'')+
|
||||
e[j].name+'='+encodeURIComponent(e[j].value);}}
|
||||
else
|
||||
{code+=(code?'&':'')+
|
||||
e.name+'='+encodeURIComponent(e.value);}}
|
||||
if(typeof extra_values=='object')
|
||||
for(var key in extra_values)
|
||||
code+=(code?'&':'')+
|
||||
key+'='+encodeURIComponent(extra_values[key]);return((form.method=='get')?this.get(form.getAttribute('action'),code,callback):this.post(form.getAttribute('action'),code,callback));}
|
||||
this._encode=function(obj)
|
||||
{obj=obj?obj:{};obj['_']=Math.random();if(typeof obj=='object')
|
||||
{var code='';var self=this;for(var k in obj)
|
||||
code+=(code?'&':'')+
|
||||
k+'='+encodeURIComponent(obj[k]);return code;}
|
||||
return obj;}}
|
||||
XHR.get=function(url,data,callback)
|
||||
{(new XHR()).get(url,data,callback);}
|
||||
XHR.poll=function(interval,url,data,callback)
|
||||
{if(isNaN(interval)||interval<1)
|
||||
interval=5;if(!XHR._q)
|
||||
{XHR._t=0;XHR._q=[];XHR._r=function(){for(var i=0,e=XHR._q[0];i<XHR._q.length;e=XHR._q[++i])
|
||||
{if(!(XHR._t%e.interval)&&!e.xhr.busy())
|
||||
e.xhr.get(e.url,e.data,e.callback);}
|
||||
XHR._t++;};}
|
||||
XHR._q.push({interval:interval,callback:callback,url:url,data:data,xhr:new XHR()});XHR.run();}
|
||||
XHR.halt=function()
|
||||
{if(XHR._i)
|
||||
{try{document.getElementById('xhr_poll_status').style.display='';document.getElementById('xhr_poll_status_on').style.display='none';document.getElementById('xhr_poll_status_off').style.display='';document.getElementById('notice_status').style.marginRight='30px'}catch(e){}
|
||||
window.clearInterval(XHR._i);XHR._i=null;}}
|
||||
XHR.run=function()
|
||||
{if(XHR._r&&!XHR._i)
|
||||
{try{document.getElementById('xhr_poll_status').style.display='';document.getElementById('xhr_poll_status_on').style.display='';document.getElementById('xhr_poll_status_off').style.display='none';document.getElementById('notice_status').style.marginRight='30px'}catch(e){}
|
||||
XHR._r();XHR._i=window.setInterval(XHR._r,1000);}}
|
||||
XHR.running=function()
|
||||
{return!!(XHR._r&&XHR._i);};(function($){function settingsStatusRealtimeOverflow(){if(self.location.pathname.includes("status/realtime")){const nodeStatusRealtime=$('.node-status-realtime');const selectorValues=['bandwidth','wifirate','wireless'];for(let i=0;i<selectorValues.length;i++){const value=selectorValues[i];const target=nodeStatusRealtime.find(`embed[src="/luci-static/resources/${value}.svg"] + div + br + table`);if(target.length){target.wrap('<div style="overflow-x: auto;"></div>');}}}}
|
||||
$(document).ready(()=>{settingsStatusRealtimeOverflow();});})(jQuery);
|
2
luci-theme-design/htdocs/luci-static/design/js/jquery.min.js
vendored
Normal file
19
luci-theme-design/htdocs/luci-static/design/js/script.js
Normal file
@ -0,0 +1,19 @@
|
||||
(function($){$(".main > .loading").fadeOut();function trimText(text){return text.replace(/[ \t\n\r]+/g," ");}
|
||||
var lastNode=undefined;var mainNodeName=undefined;var nodeUrl="";(function(node){if(node[0]=="admin"){luciLocation=[node[1],node[2]];}else{luciLocation=node;}
|
||||
for(var i in luciLocation){nodeUrl+=luciLocation[i];if(i!=luciLocation.length-1){nodeUrl+="/";}}})(luciLocation);function getCurrentNodeByUrl(){if(!$('body').hasClass('logged-in')){luciLocation=["Main","Login"];return true;}
|
||||
const urlReg=new RegExp(nodeUrl+"$")
|
||||
var ret=false;$(".main > .main-left > .nav > .slide > .active").next(".slide-menu").stop(true).slideUp("fast");$(".main > .main-left > .nav > .slide > .menu").removeClass("active");$(".main > .main-left > .nav > .slide > .menu").each(function(){var ulNode=$(this);ulNode.next().find("a").each(function(){var that=$(this);var href=that.attr("href");if(urlReg.test(href)){ulNode.click();ulNode.next(".slide-menu").stop(true,true);lastNode=that.parent();lastNode.addClass("active");ret=true;return true;}});});return ret;}
|
||||
$(".main > .main-left > .nav > .slide > .menu").click(function(){var ul=$(this).next(".slide-menu");var menu=$(this);if(!menu.hasClass("exit")){$(".main > .main-left > .nav > .slide > .active").next(".slide-menu").stop(true).slideUp("fast");$(".main > .main-left > .nav > .slide > .menu").removeClass("active");if(!ul.is(":visible")){menu.addClass("active");ul.addClass("active");ul.stop(true).slideDown("fast");}else{ul.stop(true).slideUp("fast",function(){menu.removeClass("active");ul.removeClass("active");});}
|
||||
return false;}});$(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function(){if(lastNode!=undefined)
|
||||
lastNode.removeClass("active");$(this).parent().addClass("active");$(".main > .loading").fadeIn("fast");return true;});$(".main > .main-left > .nav > .slide > .slide-menu > li").click(function(){if(lastNode!=undefined)
|
||||
lastNode.removeClass("active");$(this).addClass("active");$(".main > .loading").fadeIn("fast");window.location=$($(this).find("a")[0]).attr("href");return false;});if(getCurrentNodeByUrl()){mainNodeName="node-"+luciLocation[0]+"-"+luciLocation[1];mainNodeName=mainNodeName.replace(/[ \t\n\r\/]+/g,"_").toLowerCase();$("body").addClass(mainNodeName);}
|
||||
$("#maincontent > .container").find("a").each(function(){var that=$(this);var onclick=that.attr("onclick");if(onclick==undefined||onclick==""){that.click(function(){var href=that.attr("href");if(href.indexOf("#")==-1){$(".main > .loading").fadeIn("fast");return true;}});}});var showSide=false;$(".showSide").click(function(){if(showSide){$(".darkMask").stop(true).fadeOut("fast");$(".main-left").stop(true).animate({width:"0"},"fast");$(".main-right").css("overflow-y","auto");$("header>.container>.brand").css("padding","0 4.5rem")
|
||||
showSide=false;}else{$(".darkMask").stop(true).fadeIn("fast");$(".main-left").stop(true).animate({width:"18rem"},"fast");$(".main-right").css("overflow-y","hidden");$(".showSide").css("display","none");$("header").css("box-shadow","18rem 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding",'0rem')
|
||||
showSide=true;}});$(".darkMask").click(function(){if(showSide){$(".darkMask").stop(true).fadeOut("fast");$(".main-left").stop(true).animate({width:"0"},"fast");$(".main-right").css("overflow-y","auto");$(".showSide").css("display","");$("header").css("box-shadow","0 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding","0 4.5rem")
|
||||
showSide=false;}});$(window).resize(function(){if($(window).width()>992){showSide=false;$(".showSide").css("display","");$(".main-left").css("width","");$(".darkMask").stop(true);$(".darkMask").css("display","none");$("header").css("box-shadow","18rem 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding",'0rem')}else{$("header").css("box-shadow","0 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding","0 4.5rem")}
|
||||
if(showSide){$("header").css("box-shadow","18rem 2px 4px rgb(0 0 0 / 8%)")
|
||||
$("header>.container>.brand").css("padding",'0rem')}});$(".main-right").focus();$(".main-right").blur();$("input").attr("size","0");if(mainNodeName!=undefined){switch(mainNodeName){case "node-status-system_log":case "node-status-kernel_log":$("#syslog").focus(function(){$("#syslog").blur();$(".main-right").focus();$(".main-right").blur();});break;case "node-status-firewall":var button=$(".node-status-firewall > .main fieldset li > a");button.addClass("cbi-button cbi-button-reset a-to-btn");break;case "node-system-reboot":var button=$(".node-system-reboot > .main > .main-right p > a");button.addClass("cbi-button cbi-input-reset a-to-btn");break;}}})(jQuery);
|
25
luci-theme-design/htdocs/luci-static/design/manifest.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name":"Design",
|
||||
"short_name":"Design",
|
||||
"description":"Design for OpenWRT by gngpp.",
|
||||
"start_url":"/",
|
||||
"scope": "/",
|
||||
"orientation":"portrait",
|
||||
"display":"standalone",
|
||||
"prompt_message":"在主屏幕添加图标,以便快速访问 Design",
|
||||
"icons":[
|
||||
{
|
||||
"src":"images/icon.png",
|
||||
"sizes":"144x144",
|
||||
"type":"image/png"
|
||||
},
|
||||
{
|
||||
"src":"images/icon.png",
|
||||
"sizes":"192x192",
|
||||
"type":"image/png"
|
||||
}
|
||||
],
|
||||
"gcm_sender_id":"524223308106",
|
||||
"gcm_user_visible_only":true,
|
||||
"status":"ok"
|
||||
}
|
69
luci-theme-design/luasrc/view/themes/design/footer.htm
Normal file
@ -0,0 +1,69 @@
|
||||
<%#
|
||||
Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
|
||||
|
||||
luci-theme-material
|
||||
Copyright 2015 Lutty Yang <lutty@wcan.in>
|
||||
|
||||
luci-theme-neobird
|
||||
Copyright 2021 2smile <thinktip@gmail.com>
|
||||
|
||||
luci-theme-design
|
||||
Copyright 2023 gngpp <gngppz@gmail.com>
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
https://github.com/LuttyYang/luci-theme-material/issues
|
||||
|
||||
luci-theme-bootstrap:
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
|
||||
MUI:
|
||||
https://github.com/muicss/mui
|
||||
|
||||
Licensed to the public under the Apache License 2.0
|
||||
-%>
|
||||
|
||||
<%
|
||||
local ver = require "luci.version"
|
||||
local disp = require "luci.dispatcher"
|
||||
local request = disp.context.path
|
||||
local category = request[1]
|
||||
local tree = disp.node()
|
||||
local categories = disp.node_childs(tree)
|
||||
%>
|
||||
</div>
|
||||
<footer class="footer" style="text-align:center">
|
||||
<a href="https://github.com/openwrt/luci">Powered by <%= ver.luciname %></a> |
|
||||
<a href="https://www.lede-project.org/"><%= ver.distversion %></a>
|
||||
<br />
|
||||
© 2021-2022 2smile. All Rights Reserved.
|
||||
<% if #categories > 1 then %>
|
||||
<ul class="breadcrumb pull-right" id="modemenu">
|
||||
<% for i, r in ipairs(categories) do %>
|
||||
<li<% if category == r then %> class="active"<%end%>><a href="<%=controller%>/<%=r%>/"><%=striptags(translate(tree.nodes[r].title))%></a> <span class="divider">|</span></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(".cbi-button-up").val("");
|
||||
$(".cbi-button-down").val("");
|
||||
// fix legend position
|
||||
$("legend").each(function () {
|
||||
var that = $(this);
|
||||
that.after("<span class='panel-title'>" + that.text() + "</span>");
|
||||
});
|
||||
// Fixed openclash plugin causing env(safe-area-inset-bottom) to be 0 under
|
||||
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) && self.location.pathname.indexOf("openclash") != -1) {
|
||||
var oMeta = document.createElement('meta');
|
||||
oMeta.content = 'width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover';
|
||||
oMeta.name = 'viewport';
|
||||
document.querySelector('head').appendChild(oMeta);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
323
luci-theme-design/luasrc/view/themes/design/header.htm
Normal file
@ -0,0 +1,323 @@
|
||||
<%#
|
||||
Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
|
||||
|
||||
luci-theme-material
|
||||
Copyright 2015 Lutty Yang <lutty@wcan.in>
|
||||
|
||||
luci-theme-neobird
|
||||
Copyright 2021 2smile <thinktip@gmail.com>
|
||||
|
||||
luci-theme-design
|
||||
Copyright 2023 2smile <gngppz@gmail.com>
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
https://github.com/gngpp/luci-theme-design
|
||||
|
||||
luci-theme-bootstrap:
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
|
||||
MUI:
|
||||
https://github.com/muicss/mui
|
||||
|
||||
Licensed to the public under the Apache License 2.0
|
||||
-%>
|
||||
|
||||
<%
|
||||
local ver = require "luci.version"
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
local http = require "luci.http"
|
||||
local disp = require "luci.dispatcher"
|
||||
local uci = require 'luci.model.uci'.cursor()
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local boardinfo = util.ubus("system", "board")
|
||||
local boardinfo={}
|
||||
boardinfo.hostname=sys.hostname()
|
||||
|
||||
local request = disp.context.path
|
||||
local request2 = disp.context.request
|
||||
|
||||
local category = request[1]
|
||||
local cattree = category and disp.node(category)
|
||||
|
||||
local leaf = request2[#request2]
|
||||
|
||||
local tree = disp.node()
|
||||
local node = disp.context.dispatched
|
||||
|
||||
local categories = disp.node_childs(tree)
|
||||
|
||||
local c = tree
|
||||
local i, r
|
||||
|
||||
-- tag all nodes leading to this page
|
||||
for i, r in ipairs(request) do
|
||||
if c.nodes and c.nodes[r] then
|
||||
c = c.nodes[r]
|
||||
c._menu_selected = true
|
||||
end
|
||||
end
|
||||
|
||||
-- send as HTML5
|
||||
http.prepare_content("text/html")
|
||||
|
||||
local function nodeurl(prefix, name, query)
|
||||
local url = controller .. prefix .. name .. "/"
|
||||
if query then
|
||||
url = url .. http.build_querystring(query)
|
||||
end
|
||||
return pcdata(url)
|
||||
end
|
||||
|
||||
local function subtree(prefix, node, level)
|
||||
if not level then
|
||||
level = 1
|
||||
end
|
||||
|
||||
local childs = disp.node_childs(node)
|
||||
if #childs > 0 then
|
||||
|
||||
if level > 2 then
|
||||
%>
|
||||
<ul class="tabs">
|
||||
<%
|
||||
end
|
||||
|
||||
local selected_node
|
||||
local selected_name
|
||||
local i, v
|
||||
|
||||
for i, v in ipairs(childs) do
|
||||
local nnode = node.nodes[v]
|
||||
if nnode._menu_selected then
|
||||
selected_node = nnode
|
||||
selected_name = v
|
||||
end
|
||||
if level > 2 then
|
||||
%>
|
||||
<li class="tabmenu-item-<%=v%><%- if nnode._menu_selected or (node.leaf and v == leaf) then %> active<% end %>">
|
||||
<a href="<%=nodeurl(prefix, v, nnode.query)%>"><%=striptags(translate(nnode.title))%></a>
|
||||
</li>
|
||||
<% end
|
||||
end
|
||||
|
||||
if level > 2 then
|
||||
%>
|
||||
</ul>
|
||||
<% end
|
||||
|
||||
if selected_node then
|
||||
subtree(prefix .. selected_name .. "/", selected_node, level + 1)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Custom settings
|
||||
local mode = 'normal'
|
||||
local navbar = 'display'
|
||||
local navbar_proxy = 'shadowsocksr'
|
||||
if fs.access('/etc/config/design') then
|
||||
mode = uci:get_first('design', 'global', 'mode')
|
||||
navbar = uci:get_first('design', 'global', 'navbar')
|
||||
navbar_proxy = uci:get_first('design', 'global', 'navbar_proxy')
|
||||
end
|
||||
-%>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%=luci.i18n.context.lang%>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover" />
|
||||
<link rel="manifest" href="<%=media%>/manifest.json">
|
||||
<title><%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI</title>
|
||||
<meta name="format-detection" content="telephone=no, email=no"/>
|
||||
<meta name="x5-fullscreen" content="true">
|
||||
<meta name="full-screen" content="yes">
|
||||
<meta name="x5-page-mode" content="app">
|
||||
<meta name="browsermode" content="application">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<meta name="application-name" content="<%=striptags( (boardinfo.hostname or "?") ) %>">
|
||||
<meta name="apple-mobile-web-app-title" content="<%=striptags( (boardinfo.hostname or "?") ) %>">
|
||||
<meta name="msapplication-TileImage" content="<%=media%>/images/icon.png"/>
|
||||
<link rel="icon" href="<%=media%>/images/icon.png">
|
||||
<link rel="apple-touch-icon" href="<%=media%>/images/apple-touch-icon.png">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-touch-fullscreen" content="yes" />
|
||||
<link rel="stylesheet" href="<%=media%>/css/style.css?v=<%= ver.luciversion %>">
|
||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="white">
|
||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black">
|
||||
|
||||
<link rel="shortcut icon" href="<%=media%>/favicon.ico">
|
||||
<% if node and node.css then %>
|
||||
<link rel="stylesheet" href="<%=resource%>/<%=node.css%>">
|
||||
<% end -%>
|
||||
<% if css then %>
|
||||
<style title="text/css">
|
||||
<%-= css %>
|
||||
</style>
|
||||
<% end -%>
|
||||
<script src="<%=media%>/js/jquery.min.js?v=<%= ver.luciversion %>"></script>
|
||||
<script src="<%=media%>/js/design.js?v=<%= ver.luciversion %>"></script>
|
||||
</head>
|
||||
|
||||
<body class="lang_<%=luci.i18n.context.lang%> <%- if node then %><%= striptags( node.title ) %><%- end %> <% if luci.dispatcher.context.authsession then %>logged-in<% end %>"
|
||||
<% if mode ~= 'normal' then %>
|
||||
data-theme = "<%= mode %>"
|
||||
<% end -%>
|
||||
>
|
||||
|
||||
<header>
|
||||
<% if mode == 'normal' then %>
|
||||
<script>
|
||||
function setTheme() {
|
||||
let color_scheme = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
document.body.setAttribute('data-theme', color_scheme.matches? 'dark': 'light');
|
||||
}
|
||||
setTheme();
|
||||
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', setTheme);
|
||||
</script>
|
||||
<% end -%>
|
||||
|
||||
<% if navbar == 'display' then %>
|
||||
<style>
|
||||
:root {
|
||||
--vssrBottom: 50px;
|
||||
}
|
||||
</style>
|
||||
<div class="navbar">
|
||||
<% else %>
|
||||
<style>
|
||||
:root {
|
||||
--vssrBottom: 0px;
|
||||
}
|
||||
</style>
|
||||
<div class="navbar" style="display: none;">
|
||||
<% end -%>
|
||||
<a href="/cgi-bin/luci/admin/status/overview"><img src="<%=media%>/images/home.png" /></a>
|
||||
<% if navbar_proxy == 'openclash' then %>
|
||||
<a href="/cgi-bin/luci/admin/services/<%=navbar_proxy%>"><img src="<%=media%>/images/<%=navbar_proxy%>.png" /></a>
|
||||
<% else %>
|
||||
<a href="/cgi-bin/luci/admin/services/<%=navbar_proxy%>"><img src="<%=media%>/images/ssr.png" /></a>
|
||||
<% end -%>
|
||||
<a href="/cgi-bin/luci/admin/network/network"><img src="<%=media%>/images/link.png" /></a>
|
||||
<a href="/cgi-bin/luci/admin/status/realtime"><img src="<%=media%>/images/rank.png" /></a>
|
||||
<a href="/cgi-bin/luci/admin/system/admin"><img src="<%=media%>/images/user.png" /></a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<span class="showSide"></span>
|
||||
<a class="brand" href="#"><%=boardinfo.hostname or "OpenWrt"%></a>
|
||||
<div class="pull-right">
|
||||
<script>
|
||||
if ($(window).width() > 992) {
|
||||
$("header>.container>.brand").css("padding", "0 0px")
|
||||
}
|
||||
</script>
|
||||
<%
|
||||
-- calculate the number of unsaved changes
|
||||
if tree.nodes[category] and tree.nodes[category].ucidata then
|
||||
local ucichanges = 0
|
||||
for i, j in pairs(require("luci.model.uci").cursor():changes()) do
|
||||
for k, l in pairs(j) do
|
||||
for m, n in pairs(l) do
|
||||
ucichanges = ucichanges + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
%>
|
||||
<% if ucichanges > 0 then %>
|
||||
<style>
|
||||
.notice:after {
|
||||
content: "<%=ucichanges%>";
|
||||
font-size: 0.8rem;
|
||||
font-family: Tahoma;
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
</style>
|
||||
<a id="notice_status" class="label notice" href="<%=url(category, 'uci/changes')%>?redir=<%=http.urlencode(http.formvalue('redir') or table.concat(disp.context.request, "/"))%>"></a>
|
||||
<% end %>
|
||||
<span id="xhr_poll_status" style="display:none" onclick="XHR.running() ? XHR.halt() : XHR.run()">
|
||||
<span class="label success" id="xhr_poll_status_on"><span id="refresh_on" class="mobile-hide"></span></span>
|
||||
<span class="label" id="xhr_poll_status_off" style="display:none"><span id="refresh_off" class="mobile-hide"></span></span>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main">
|
||||
<div class="main-left">
|
||||
<ul class="nav">
|
||||
<%-
|
||||
local function submenu(prefix, node)
|
||||
local childs = disp.node_childs(node)
|
||||
if #childs > 0 then
|
||||
%>
|
||||
<ul class="slide-menu">
|
||||
<%-
|
||||
for i, r in ipairs(childs) do
|
||||
local nnode = node.nodes[r]
|
||||
local href = controller .. "" .. prefix .. r ..
|
||||
(nnode.query and http.build_querystring(nnode.query) or "")
|
||||
%>
|
||||
<li><a data-title="<%=pcdata(striptags(nnode.title))%>" href="<%=pcdata(href)%>"><%=pcdata(striptags(translate(nnode.title)))%></a></li>
|
||||
<%-
|
||||
end
|
||||
%>
|
||||
</ul>
|
||||
<%-
|
||||
end
|
||||
end
|
||||
|
||||
childs = disp.node_childs(cattree)
|
||||
|
||||
if #childs > 0 then
|
||||
for i, r in ipairs(childs) do
|
||||
local nnode = cattree.nodes[r]
|
||||
local href = controller .. "/" .. category .. "/" .. r ..
|
||||
(nnode.query and http.build_querystring(k.query) or "")
|
||||
local grandchildren = disp.node_childs(nnode)
|
||||
|
||||
if #grandchildren > 0 then
|
||||
%>
|
||||
<li class="slide">
|
||||
<a class="menu" data-title="<%=pcdata(striptags(nnode.title))%>" href="#"><%=pcdata(striptags(translate(nnode.title)))%></a>
|
||||
<%- submenu("" .. category .. "/" .. r .. "/", nnode) %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li class="slide">
|
||||
<a class="menu2" data-title="<%=pcdata(striptags(nnode.title))%>" href="<%=pcdata(href)%>"><%=pcdata(striptags(translate(nnode.title)))%></a>
|
||||
</li>
|
||||
<%
|
||||
end
|
||||
end
|
||||
end
|
||||
%>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="main-right">
|
||||
<div class="darkMask"></div>
|
||||
<div id="maincontent">
|
||||
<div class="container">
|
||||
<%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%>
|
||||
<div class="alert-message warning">
|
||||
<h4><%:No password set!%></h4>
|
||||
<%:There is no password set on this router. Please configure a root password to protect the web interface and enable SSH.%><br>
|
||||
<a href="<%=pcdata(luci.dispatcher.build_url("admin/system/admin"))%>"><%:Go to password configuration...%></a>
|
||||
</div>
|
||||
<%- end -%>
|
||||
<% if category then subtree("/" .. category .. "/", cattree) end %>
|
||||
|
||||
<script>
|
||||
// thanks for Jo-Philipp Wich <jow@openwrt.org>
|
||||
var luciLocation = <%= luci.http.write_json(luci.dispatcher.context.path) %>;
|
||||
</script>
|
||||
<script src="<%=media%>/js/script.js?v=<%= ver.luciversion %>"></script>
|
BIN
luci-theme-design/preview/IMG_0328.PNG
Normal file
After Width: | Height: | Size: 257 KiB |
BIN
luci-theme-design/preview/IMG_0329.PNG
Normal file
After Width: | Height: | Size: 373 KiB |
BIN
luci-theme-design/preview/firewall.png
Normal file
After Width: | Height: | Size: 310 KiB |
BIN
luci-theme-design/preview/home.png
Normal file
After Width: | Height: | Size: 324 KiB |
BIN
luci-theme-design/preview/home1.png
Normal file
After Width: | Height: | Size: 309 KiB |
BIN
luci-theme-design/preview/iface.png
Normal file
After Width: | Height: | Size: 468 KiB |
BIN
luci-theme-design/preview/light.png
Normal file
After Width: | Height: | Size: 333 KiB |
BIN
luci-theme-design/preview/login.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
luci-theme-design/preview/login1.png
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
luci-theme-design/preview/page.png
Normal file
After Width: | Height: | Size: 306 KiB |
BIN
luci-theme-design/preview/webapp_home.PNG
Normal file
After Width: | Height: | Size: 415 KiB |
BIN
luci-theme-design/preview/webapp_vssr.PNG
Normal file
After Width: | Height: | Size: 561 KiB |
BIN
luci-theme-design/preview/wifi.png
Normal file
After Width: | Height: | Size: 393 KiB |
11
luci-theme-design/root/etc/uci-defaults/30_luci-theme-design
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$PKG_UPGRADE" != 1 ]; then
|
||||
uci batch <<-EOF
|
||||
set luci.themes.Design=/luci-static/design
|
||||
set luci.main.mediaurlbase=/luci-static/design
|
||||
commit luci
|
||||
EOF
|
||||
fi
|
||||
|
||||
exit 0
|