luci-base: support hiding the "Back to Overview" button in cbi maps
[project/luci.git] / applications / luci-app-travelmate / luasrc / model / cbi / travelmate / overview_tab.lua
index b16fb41..e2f4e3f 100644 (file)
@@ -1,15 +1,17 @@
--- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
 -- This is free software, licensed under the Apache License, Version 2.0
 
-local fs = require("nixio.fs")
-local uci = require("luci.model.uci").cursor()
-local json = require("luci.jsonc")
-local nw  = require("luci.model.network").init()
-local fw  = require("luci.model.firewall").init()
-local trmiface = uci.get("travelmate", "global", "trm_iface") or "trm_wwan"
-local trminput = uci.get("travelmate", "global", "trm_rtfile") or "/tmp/trm_runtime.json"
-local uplink = uci.get("network", trmiface) or ""
-local parse = json.parse(fs.readfile(trminput) or "")
+local fs       = require("nixio.fs")
+local uci      = require("luci.model.uci").cursor()
+local json     = require("luci.jsonc")
+local util     = require("luci.util")
+local nw       = require("luci.model.network").init()
+local fw       = require("luci.model.firewall").init()
+local dump     = util.ubus("network.interface", "dump", {})
+local trmiface = uci:get("travelmate", "global", "trm_iface") or "trm_wwan"
+local trminput = uci:get("travelmate", "global", "trm_rtfile") or "/tmp/trm_runtime.json"
+local uplink   = uci:get("network", trmiface) or ""
+local parse    = json.parse(fs.readfile(trminput) or "")
 
 m = Map("travelmate", translate("Travelmate"),
        translate("Configuration of the travelmate package to to enable travel router functionality. ")
@@ -17,105 +19,106 @@ m = Map("travelmate", translate("Travelmate"),
        .. "<a href=\"%s\" target=\"_blank\">"
        .. "see online documentation</a>", "https://github.com/openwrt/packages/blob/master/net/travelmate/files/README.md"))
 
+-- We might modify these configs too:
+m:chain("network")
+m:chain("firewall")
+
 function m.on_after_commit(self)
-       luci.sys.call("/etc/init.d/travelmate restart >/dev/null 2>&1")
+       uci:apply(true)
        luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
 end
 
-s = m:section(NamedSection, "global", "travelmate")
-
 -- Interface Wizard
 
 if uplink == "" then
-       dv = s:option(DummyValue, "nil", translate("Interface Wizard"))
-       dv.template = "cbi/nullsection"
+       ds = m:section(NamedSection, "global", "travelmate", translate("Interface Wizard"))
 
-       o = s:option(Value, "trm_iface", translate("Uplink interface"))
+       o = ds:option(Value, "", translate("Uplink interface"))
        o.datatype = "and(uciname,rangelength(3,15))"
-       o.default = "trm_wwan"
+       o.default = trmiface
        o.rmempty = false
 
-       btn = s:option(Button, "", translate("Create Uplink Interface"),
+       btn = ds:option(Button, "trm_iface", translate("Create Uplink Interface"),
                translate("Create a new wireless wan uplink interface, configure it to use dhcp and ")
                .. translate("add it to the wan zone of the firewall. This step has only to be done once."))
        btn.inputtitle = translate("Add Interface")
        btn.inputstyle = "apply"
        btn.disabled = false
-       function btn.write(self, section, value)
-               iface = o:formvalue(section)
-               uci:set("travelmate", section, "trm_iface", iface)
-               uci:save("travelmate")
-               uci:commit("travelmate")
-               local net = nw:add_network(iface, { proto = "dhcp" })
-               if net then
-                       nw:save("network")
-                       nw:commit("network")
-                       local zone = fw:get_zone_by_network("wan")
-                       if zone then
-                               zone:add_network(iface)
-                               fw:save("firewall")
-                               fw:commit("firewall")
-                               luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>&1")
+
+       function btn.write(self, section)
+               -- Do uci changes. Note that we must not commit here as the rollback handler
+               -- needs to see "unsaved changes" in order to roll them back.
+               local iface = o:formvalue(section)
+               if iface then
+                       uci:set("travelmate", section, "trm_iface", iface)
+                       local net = nw:add_network(iface, { proto = "dhcp" })
+                       if net then
+                               local zone = fw:get_zone_by_network("wan")
+                               if zone then
+                                       zone:add_network(iface)
+                               end
                        end
                end
-               luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
+
+               -- Since we're prematurely terminating the cbi logic flow here and since we trigger
+               -- our modifications in a button write callback and not via cbi.apply, we do need to
+               -- tell cbi to trigger apply/rollback.
+               m.flow.autoapply = true
        end
        return m
 end
 
 -- Main travelmate options
 
+s = m:section(NamedSection, "global", "travelmate")
+
 o1 = s:option(Flag, "trm_enabled", translate("Enable travelmate"))
 o1.default = o1.disabled
 o1.rmempty = false
 
-o2 = s:option(Flag, "trm_automatic", translate("Enable 'automatic' mode"),
-       translate("Keep travelmate in an active state. Check every n seconds the connection status, i.e. the uplink availability."))
+o2 = s:option(Flag, "trm_captive", translate("Captive Portal Detection"),
+       translate("Check the internet availability, log captive portal redirections and keep the uplink connection 'alive'."))
 o2.default = o2.enabled
 o2.rmempty = false
 
-btn = s:option(Button, "", translate("Manual Rescan"))
-btn:depends("trm_automatic", "")
-btn.inputtitle = translate("Rescan")
-btn.inputstyle = "find"
-btn.disabled = false
-function btn.write()
-       luci.sys.call("/etc/init.d/travelmate start >/dev/null 2>&1")
-       luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
+o3 = s:option(ListValue, "trm_iface", translate("Uplink / Trigger interface"),
+       translate("Name of the used uplink interface."))
+if dump then
+       local i, v
+       for i, v in ipairs(dump.interface) do
+               if v.interface ~= "loopback" and v.interface ~= "lan" then
+                       o3:value(v.interface)
+               end
+       end
 end
-
-o3 = s:option(Value, "trm_iface", translate("Uplink / Trigger interface"),
-       translate("Name of the uplink interface that triggers travelmate processing in 'manual' mode."))
-o3.datatype = "and(uciname,rangelength(3,15))"
 o3.default = trmiface
 o3.rmempty = false
 
-o4 = s:option(Value, "trm_triggerdelay", translate("Trigger delay"),
-       translate("Additional trigger delay in seconds before travelmate processing begins."))
-o4.default = 2
-o4.datatype = "range(1,90)"
-o4.rmempty = false
+if fs.access("/usr/bin/qrencode") then
+       btn = s:option(Button, "btn", translate("View AP QR-Codes"),
+               translate("Connect your Android or iOS devices to your router's WiFi using the shown QR code."))
+       btn.inputtitle = translate("QR-Codes")
+       btn.inputstyle = "apply"
+       btn.disabled = false
 
-o5 = s:option(Flag, "trm_debug", translate("Enable verbose debug logging"))
-o5.default = o5.disabled
-o5.rmempty = false
+       function btn.write()
+               luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate", "apqr"))
+       end
+end
 
 -- Runtime information
 
-ds = s:option(DummyValue, "_dummy", translate("Runtime information"))
-ds.template = "cbi/nullsection"
+ds = m:section(NamedSection, "global", "travelmate", translate("Runtime Information"))
 
-dv1 = s:option(DummyValue, "status", translate("Online Status"))
+dv1 = ds:option(DummyValue, "status", translate("Travelmate Status (Quality)"))
 dv1.template = "travelmate/runtime"
-if parse == nil then
-       dv1.value = translate("n/a")
-elseif parse.data.station_connection == "true" then
-       dv1.value = translate("connected")
+if parse ~= nil then
+       dv1.value = parse.data.travelmate_status or translate("n/a")
 else
-       dv1.value = translate("not connected")
+       dv1.value = translate("n/a")
 end
 
-dv2 = s:option(DummyValue, "travelmate_version", translate("Travelmate version"))
+dv2 = ds:option(DummyValue, "travelmate_version", translate("Travelmate Version"))
 dv2.template = "travelmate/runtime"
 if parse ~= nil then
        dv2.value = parse.data.travelmate_version or translate("n/a")
@@ -123,15 +126,15 @@ else
        dv2.value = translate("n/a")
 end
 
-dv3 = s:option(DummyValue, "station_ssid", translate("Station SSID"))
+dv3 = ds:option(DummyValue, "station_id", translate("Station ID (SSID/BSSID)"))
 dv3.template = "travelmate/runtime"
 if parse ~= nil then
-       dv3.value = parse.data.station_ssid or translate("n/a")
+       dv3.value = parse.data.station_id or translate("n/a")
 else
        dv3.value = translate("n/a")
 end
 
-dv4 = s:option(DummyValue, "station_interface", translate("Station Interface"))
+dv4 = ds:option(DummyValue, "station_interface", translate("Station Interface"))
 dv4.template = "travelmate/runtime"
 if parse ~= nil then
        dv4.value = parse.data.station_interface or translate("n/a")
@@ -139,7 +142,7 @@ else
        dv4.value = translate("n/a")
 end
 
-dv5 = s:option(DummyValue, "station_radio", translate("Station Radio"))
+dv5 = ds:option(DummyValue, "station_radio", translate("Station Radio"))
 dv5.template = "travelmate/runtime"
 if parse ~= nil then
        dv5.value = parse.data.station_radio or translate("n/a")
@@ -147,7 +150,7 @@ else
        dv5.value = translate("n/a")
 end
 
-dv6 = s:option(DummyValue, "last_rundate", translate("Last rundate"))
+dv6 = ds:option(DummyValue, "last_rundate", translate("Last rundate"))
 dv6.template = "travelmate/runtime"
 if parse ~= nil then
        dv6.value = parse.data.last_rundate or translate("n/a")
@@ -160,26 +163,43 @@ end
 e = m:section(NamedSection, "global", "travelmate", translate("Extra options"),
 translate("Options for further tweaking in case the defaults are not suitable for you."))
 
-e1 = e:option(Value, "trm_radio", translate("Radio selection"),
-       translate("Restrict travelmate to a dedicated radio, e.g. 'radio0'"))
-e1.rmempty = true
+e1 = e:option(Flag, "trm_debug", translate("Enable verbose debug logging"))
+e1.default = e1.disabled
+e1.rmempty = false
 
-e2 = e:option(Value, "trm_maxretry", translate("Connection Limit"),
-       translate("How many times should travelmate try to connect to an Uplink"))
-e2.default = 3
-e2.datatype = "range(1,10)"
-e2.rmempty = false
+e2 = e:option(Value, "trm_radio", translate("Radio selection"),
+       translate("Restrict travelmate to a dedicated radio, e.g. 'radio0'."))
+e2.datatype = "and(uciname,rangelength(6,6))"
+e2.rmempty = true
 
-e3 = e:option(Value, "trm_maxwait", translate("Interface Timeout"),
-       translate("How long should travelmate wait for a successful wlan interface reload"))
-e3.default = 30
-e3.datatype = "range(5,60)"
+e3 = e:option(Value, "trm_triggerdelay", translate("Trigger Delay"),
+       translate("Additional trigger delay in seconds before travelmate processing begins."))
+e3.datatype = "range(1,60)"
+e3.default = 2
 e3.rmempty = false
 
-e4 = e:option(Value, "trm_timeout", translate("Overall Timeout"),
-       translate("Timeout in seconds between retries in 'automatic' mode"))
-e4.default = 60
-e4.datatype = "range(5,300)"
+e4 = e:option(Value, "trm_maxretry", translate("Connection Limit"),
+       translate("Retry limit to connect to an uplink."))
+e4.default = 3
+e4.datatype = "range(1,10)"
 e4.rmempty = false
 
+e5 = e:option(Value, "trm_minquality", translate("Signal Quality Threshold"),
+       translate("Minimum signal quality threshold as percent for conditional uplink (dis-) connections."))
+e5.default = 35
+e5.datatype = "range(20,80)"
+e5.rmempty = false
+
+e6 = e:option(Value, "trm_maxwait", translate("Interface Timeout"),
+       translate("How long should travelmate wait for a successful wlan uplink connection."))
+e6.default = 30
+e6.datatype = "range(20,40)"
+e6.rmempty = false
+
+e7 = e:option(Value, "trm_timeout", translate("Overall Timeout"),
+       translate("Overall retry timeout in seconds."))
+e7.default = 60
+e7.datatype = "range(30,300)"
+e7.rmempty = false
+
 return m