Add a New Dropdown Menu in OpenWRT LUCI
Reading time: 50 – 82 minutesOpenWRT, the popular open-source Linux operating system designed for embedded devices, offers the LUCI interface for easy configuration and management. LUCI is essentially the web interface for OpenWRT, and while it’s already feature-rich, sometimes you may want to extend its functionalities based on your needs.
Recently, I had a requirement to enhance my OpenWRT LUCI interface. Specifically, I wanted to introduce a new menu named “Apps” in the LUCI dashboard. The objective was to have each entry within this new menu link to different applications installed on my device. And not just that! I wanted these application pages to pop open in new tabs for ease of access.
The Solution
The changes were made in a single file located at:
<code>/usr/lib/lua/luci/controller/apps.lua</code>
Within this file, I implemented the following code:
module("luci.controller.apps", package.seeall)
function index()
local page
page = entry({"admin", "apps"}, firstchild(), _("Apps"), 60)
page.dependent = false
entry({"admin", "apps", "portainer"}, call("serve_js_redirect", "https", "9443"), _("Portainer"), 10).leaf = true
entry({"admin", "apps", "nodered"}, call("serve_js_redirect", "http", "1880"), _("NodeRED"), 20).leaf = true
entry({"admin", "apps", "grafana"}, call("serve_js_redirect", "http", "3000"), _("Grafana"), 30).leaf = true
entry({"admin", "apps", "prometheus"}, call("serve_js_redirect", "http", "9090"), _("Prometheus"), 40).leaf = true
end
function serve_js_redirect(protocol, port)
local ip = luci.http.getenv("SERVER_ADDR")
local url = protocol .. "://" .. ip .. ":" .. port
luci.http.prepare_content("text/html; charset=utf-8")
luci.http.write("<!DOCTYPE html><html><head><meta charset='UTF-8'><title>Redirecting...</title></head><body>")
luci.http.write("<script type='text/javascript'>")
luci.http.write("window.onload = function() {")
luci.http.write(" var newWindow = window.open('".. url .."', '_blank');")
luci.http.write(" if (!newWindow || newWindow.closed || typeof newWindow.closed == 'undefined') {")
luci.http.write(" document.getElementById('manualLink').style.display = 'block';")
luci.http.write(" setTimeout(function() { window.location.href = document.referrer; }, 60000);") -- Redirigir después de 60 segundos
luci.http.write(" }")
luci.http.write("}")
luci.http.write("</script>")
luci.http.write("<p id='manualLink' style='display: none;'>The window didn't open automatically. <a href='".. url .."' target='_blank'>Click here</a> to open manually.</p>")
luci.http.write("</body></html>")
end
Key Points
- The
index
function is responsible for defining the new menu and its entries. - The
serve_js_redirect
function creates a web page that uses JavaScript to automatically open the desired application in a new browser tab. - A failsafe mechanism is added in the form of a link. If, for any reason (like pop-up blockers), the new tab doesn’t open automatically, the user has the option to manually click on a link to open the application.
- The script also includes a feature that will redirect the user back to the previous page after 60 seconds if the new tab doesn’t open.
This modification provides a seamless way to integrate external applications directly into the LUCI interface, making navigation and management even more convenient!