@@ -11,111 +11,24 @@ fleth_style.innerHTML = `.cbi-value-field { padding-top: 6px;}</style>`;
1111document . head . appendChild ( fleth_style ) ;
1212
1313return view . extend ( {
14- // ¿
15- load : async function ( ) {
16- // Return empty data immediately to allow page to render
17- return {
18- status : [ _ ( "Loading..." ) , _ ( "Loading..." ) ] ,
19- mape_status : [ _ ( "Loading..." ) ] ,
20- } ;
21- } ,
22-
23- // Function to execute command with timeout
24- execWithTimeout : function ( cmd , args , timeout ) {
25- return Promise . race ( [
26- fs . exec ( cmd , args ) ,
27- new Promise ( ( _ , reject ) =>
28- setTimeout ( ( ) => reject ( new Error ( 'Command timeout' ) ) , timeout )
29- )
30- ] ) . catch ( err => {
31- console . warn ( `Command failed: ${ cmd } ${ args . join ( ' ' ) } ` , err ) ;
32- return { stdout : "" } ;
14+ load : function ( ) {
15+ return Promise . all ( [
16+ L . resolveDefault ( fs . exec ( "/usr/sbin/fleth" , [ "get_area" ] ) , { stdout : "" } ) ,
17+ L . resolveDefault ( fs . exec ( "/usr/sbin/fleth" , [ "get_dslite_provider" ] ) , { stdout : "" } ) ,
18+ L . resolveDefault ( fs . exec ( "/usr/sbin/fleth" , [ "mape_status" ] ) , { stdout : "" } ) ,
19+ ] ) . then ( function ( results ) {
20+ const area = ( results [ 0 ] . stdout || "" ) . trim ( ) ;
21+ const dslite_provider = ( results [ 1 ] . stdout || "" ) . trim ( ) ;
22+ const mape_status = ( results [ 2 ] . stdout || "" ) . split ( "\n" ) ;
23+
24+ return {
25+ area : area || "UNKNOWN" ,
26+ dslite_provider : dslite_provider || "UNKNOWN" ,
27+ mape_status : mape_status ,
28+ } ;
3329 } ) ;
3430 } ,
3531
36- // Load status data asynchronously after page render
37- loadStatusAsync : async function ( ) {
38- try {
39- // Execute both commands in parallel with timeout
40- const [ statusResult , mapeResult ] = await Promise . all ( [
41- this . execWithTimeout ( "/usr/sbin/fleth" , [ "status" ] , 5000 ) ,
42- this . execWithTimeout ( "/usr/sbin/fleth" , [ "mape_status" ] , 5000 )
43- ] ) ;
44-
45- const status = ( statusResult . stdout || "" ) . split ( "\n" ) ;
46- const mape_status = ( mapeResult . stdout || "" ) . split ( "\n" ) ;
47-
48- // Update area field
49- const areaElem = document . querySelector ( '[data-name="area"] .cbi-value-field' ) ;
50- let areaValue = status [ 0 ] || "UNKNOWN" ;
51- if ( areaElem && status [ 0 ] ) {
52- areaElem . textContent = _ ( status [ 0 ] || "UNKNOWN" ) ;
53- }
54-
55- // Update DS-Lite provider field
56- const dsliteElem = document . querySelector ( '[data-name="dslite_privider"] .cbi-value-field' ) ;
57- let dsliteValue = status [ 1 ] || "UNKNOWN" ;
58- if ( dsliteElem && status [ 1 ] ) {
59- dsliteElem . textContent = _ ( status [ 1 ] || "UNKNOWN" ) ;
60- }
61-
62- // Update MAP-E fields
63- let mapeIsUnknown = true ;
64- if ( mape_status . length > 1 && mape_status [ 0 ] !== "UNKNOWN" ) {
65- mapeIsUnknown = false ;
66- const mapeFields = [
67- "mape_provider" , "mape_ipaddr" , "mape_peeraddr" ,
68- "mape_ip4prefix" , "mape_ip4prefixlen" , "mape_ip6prefix" ,
69- "mape_ip6prefixlen" , "mape_ealen" , "mape_psidlen" ,
70- "mape_offset" , "mape_map_ports"
71- ] ;
72-
73- mapeFields . forEach ( ( field , i ) => {
74- const elem = document . querySelector ( `[data-name="${ field } "] .cbi-value-field` ) ;
75- if ( elem && mape_status [ i ] ) {
76- elem . textContent = mape_status [ i ] ;
77- }
78- } ) ;
79- } else {
80- // Update MAP-E Provider to UNKNOWN when not available
81- const mapeProviderElem = document . querySelector ( '[data-name="mape_provider"] .cbi-value-field' ) ;
82- if ( mapeProviderElem ) {
83- mapeProviderElem . textContent = _ ( "UNKNOWN" ) ;
84- }
85- }
86-
87- // Check pending status when area is not UNKNOWN but both DSLite and MAP-E are UNKNOWN
88- if ( areaValue !== "UNKNOWN" && dsliteValue === "UNKNOWN" && mapeIsUnknown ) {
89- try {
90- const pendingResult = await this . execWithTimeout ( "/usr/sbin/fleth" , [ "pending_status" ] , 5000 ) ;
91- const pendingStatus = ( pendingResult . stdout || "" ) . trim ( ) ;
92-
93- if ( pendingStatus === "_pending" ) {
94- // Update area field to show pending status
95- if ( areaElem ) {
96- areaElem . textContent = _ ( areaValue ) + " " + _ ( "(Service Pending)" ) ;
97- }
98- }
99- } catch ( error ) {
100- console . warn ( "Failed to check pending status:" , error ) ;
101- }
102- }
103- } catch ( error ) {
104- console . error ( "Failed to load status data:" , error ) ;
105-
106- // Set error state for fields
107- const areaElem = document . querySelector ( '[data-name="area"] .cbi-value-field' ) ;
108- if ( areaElem ) {
109- areaElem . textContent = _ ( "Failed to load" ) ;
110- }
111-
112- const dsliteElem = document . querySelector ( '[data-name="dslite_privider"] .cbi-value-field' ) ;
113- if ( dsliteElem ) {
114- dsliteElem . textContent = _ ( "Failed to load" ) ;
115- }
116- }
117- } ,
118-
11932 render : async function ( data ) {
12033 let m , s , o ;
12134
@@ -133,7 +46,7 @@ return view.extend({
13346
13447 o = s . taboption ( "info" , form . DummyValue , "area" , _ ( "Area" ) ) ;
13548 o . cfgvalue = function ( ) {
136- return _ ( data . status [ 0 ] ) ;
49+ return data . area ;
13750 } ;
13851
13952 o = s . taboption (
@@ -143,39 +56,47 @@ return view.extend({
14356 _ ( "DS-Lite Provider" )
14457 ) ;
14558 o . cfgvalue = function ( ) {
146- return _ ( data . status [ 1 ] ) ;
59+ return data . dslite_provider ;
14760 } ;
148- if ( data . mape_status . length > 1 && data . mape_status [ 0 ] !== "UNKNOWN" && data . mape_status [ 0 ] !== _ ( "Loading..." ) ) {
149- const mapeFields = [
150- [ "mape_provider" , "MAP-E Provider" ] ,
151- [ "mape_ipaddr" , "IP Address" ] ,
152- [ "mape_peeraddr" , "Peer Address" ] ,
153- [ "mape_ip4prefix" , "IPv4 prefix" ] ,
154- [ "mape_ip4prefixlen" , "IPv4 Prefix Length" ] ,
155- [ "mape_ip6prefix" , "IPv6 Prefix" ] ,
156- [ "mape_ip6prefixlen" , "IPv6 Prefix Length" ] ,
157- [ "mape_ealen" , "EA Length" ] ,
158- [ "mape_psidlen" , "PSID Length" ] ,
159- [ "mape_offset" , "Offset" ] ,
160- [ "mape_map_ports" , "Available ports" ] ,
161- ] ;
162- mapeFields . forEach ( ( field , i ) => {
163- let o = s . taboption ( "info" , form . DummyValue , field [ 0 ] , _ ( field [ 1 ] ) ) ;
164- o . cfgvalue = function ( ) {
165- return data . mape_status [ i ] ;
166- } ;
167- } ) ;
168- } else {
169- o = s . taboption (
170- "info" ,
171- form . DummyValue ,
172- "mape_provider" ,
173- _ ( "MAP-E Provider" )
174- ) ;
61+
62+ // Create all MAP-E fields
63+ const mapeFields = [
64+ [ "mape_provider" , "MAP-E Provider" ] ,
65+ [ "mape_ipaddr" , "IP Address" ] ,
66+ [ "mape_peeraddr" , "Peer Address" ] ,
67+ [ "mape_ip4prefix" , "IPv4 prefix" ] ,
68+ [ "mape_ip4prefixlen" , "IPv4 Prefix Length" ] ,
69+ [ "mape_ip6prefix" , "IPv6 Prefix" ] ,
70+ [ "mape_ip6prefixlen" , "IPv6 Prefix Length" ] ,
71+ [ "mape_ealen" , "EA Length" ] ,
72+ [ "mape_psidlen" , "PSID Length" ] ,
73+ [ "mape_offset" , "Offset" ] ,
74+ [ "mape_map_ports" , "Available ports" ] ,
75+ ] ;
76+
77+ // Check if we should hide MAP-E details initially
78+ const shouldHideMapeDetails = data . mape_status [ 0 ] === "UNKNOWN" ||
79+ data . mape_status . length <= 1 ;
80+
81+ // Create all MAP-E fields
82+ mapeFields . forEach ( ( field , i ) => {
83+ const [ fieldName , fieldLabel ] = field ;
84+ o = s . taboption ( "info" , form . DummyValue , fieldName , _ ( fieldLabel ) ) ;
17585 o . cfgvalue = function ( ) {
176- return data . mape_status [ 0 ] === _ ( "Loading..." ) ? _ ( "Loading..." ) : _ ( "UNKNOWN" ) ;
86+ if ( i === 0 ) { // MAP-E Provider field
87+ return data . mape_status [ 0 ] || _ ( "UNKNOWN" ) ;
88+ }
89+ return data . mape_status [ i ] || "" ;
17790 } ;
178- }
91+ // Add a class to identify MAP-E detail fields for hiding
92+ if ( i > 0 && shouldHideMapeDetails ) {
93+ o . rmempty = false ;
94+ o . editable = false ;
95+ // We'll hide these with CSS after render
96+ o . modalonly = false ;
97+ o . optional = true ;
98+ }
99+ } ) ;
179100
180101 // o = s.taboption('general', form.Button, '_hook_luci-firewall-port-forward');
181102 // o.title = ' ';
@@ -261,10 +182,25 @@ return view.extend({
261182 ) ;
262183 o . nocreate = true ;
263184 o . default = "wan" ;
264-
265- // Start async loading of status data after render
266- setTimeout ( ( ) => this . loadStatusAsync ( ) , 100 ) ;
185+
186+ // Hide MAP-E detail fields initially if no valid data
187+ setTimeout ( ( ) => {
188+ if ( data . mape_status [ 0 ] === "UNKNOWN" ||
189+ data . mape_status . length <= 1 ) {
190+ const mapeDetailFields = [
191+ "mape_ipaddr" , "mape_peeraddr" , "mape_ip4prefix" , "mape_ip4prefixlen" ,
192+ "mape_ip6prefix" , "mape_ip6prefixlen" , "mape_ealen" , "mape_psidlen" ,
193+ "mape_offset" , "mape_map_ports"
194+ ] ;
195+ mapeDetailFields . forEach ( field => {
196+ const fieldContainer = document . querySelector ( `[data-name="${ field } "]` ) ;
197+ if ( fieldContainer ) {
198+ fieldContainer . style . display = 'none' ;
199+ }
200+ } ) ;
201+ }
202+ } , 100 ) ;
267203
268204 return m . render ( ) ;
269205 } ,
270- } ) ;
206+ } ) ;
0 commit comments