@@ -3,135 +3,178 @@ let refreshInterval;
33async function loadEmailAccounts ( ) {
44 try {
55 const response = await fetch ( '/api/email-accounts' ) ;
6+ if ( ! response . ok ) {
7+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
8+ }
69 const accounts = await response . json ( ) ;
710 const select = document . getElementById ( 'destination' ) ;
811
9- select . innerHTML = '<option value="">Select destination email</option>' ;
10- accounts . forEach ( email => {
11- const option = document . createElement ( 'option' ) ;
12- option . value = email ;
13- option . textContent = email ;
14- select . appendChild ( option ) ;
15- } ) ;
12+ if ( accounts . error ) {
13+ select . innerHTML = '<option value="">Error loading accounts</option>' ;
14+ console . error ( 'API Error:' , accounts . error ) ;
15+ return ;
16+ }
17+
18+ // Clear and rebuild options
19+ select . innerHTML = '<option value="">Select destination</option>' ;
20+
21+ // Add email accounts from DirectAdmin
22+ if ( accounts . length > 0 ) {
23+ const optgroup = document . createElement ( 'optgroup' ) ;
24+ optgroup . label = 'Email Accounts' ;
25+ accounts . forEach ( email => {
26+ const option = document . createElement ( 'option' ) ;
27+ option . value = email ;
28+ option . textContent = email ;
29+ optgroup . appendChild ( option ) ;
30+ } ) ;
31+ select . appendChild ( optgroup ) ;
32+ }
33+
34+ // Add custom email option
35+ const customOption = document . createElement ( 'option' ) ;
36+ customOption . value = 'custom' ;
37+ customOption . textContent = '➕ Custom Email Address...' ;
38+ select . appendChild ( customOption ) ;
39+
1640 } catch ( error ) {
1741 console . error ( 'Error loading email accounts:' , error ) ;
42+ document . getElementById ( 'destination' ) . innerHTML = '<option value="">Error loading accounts</option>' ;
43+ }
44+ }
45+
46+ function toggleCustomEmail ( ) {
47+ const select = document . getElementById ( 'destination' ) ;
48+ const customGroup = document . getElementById ( 'customEmailGroup' ) ;
49+ const customInput = document . getElementById ( 'customEmail' ) ;
50+
51+ if ( select . value === 'custom' ) {
52+ customGroup . style . display = 'block' ;
53+ customInput . required = true ;
54+ customInput . focus ( ) ;
55+ } else {
56+ customGroup . style . display = 'none' ;
57+ customInput . required = false ;
58+ customInput . value = '' ;
1859 }
1960}
2061
2162async function loadForwarders ( ) {
2263 try {
2364 const response = await fetch ( '/api/forwarders' ) ;
65+ if ( ! response . ok ) {
66+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
67+ }
2468 const forwarders = await response . json ( ) ;
2569 const list = document . getElementById ( 'forwardersList' ) ;
2670
71+ if ( forwarders . error ) {
72+ list . innerHTML = '<p class="error">Error loading forwarders: ' + forwarders . error + '</p>' ;
73+ return ;
74+ }
75+
2776 if ( forwarders . length === 0 ) {
28- list . innerHTML = '<p>No forwarders configured</p>' ;
77+ list . innerHTML = '<p class="no-forwarders" >No forwarders configured</p>' ;
2978 return ;
3079 }
3180
81+ // Create formatted list of forwarders
3282 list . innerHTML = forwarders . map ( f => `
3383 <div class="forwarder-item">
34- <div>
35- <strong>${ f . alias } </strong> → ${ f . destinations . join ( ', ' ) }
84+ <div class="forwarder-info">
85+ <span class="forwarder-alias">${ f . alias } </span>
86+ <span class="forwarder-arrow">→</span>
87+ <div class="forwarder-destinations">
88+ ${ f . destinations . map ( dest => `<span class="destination-tag">${ dest } </span>` ) . join ( '' ) }
89+ </div>
3690 </div>
3791 <button class="delete-btn" onclick="deleteForwarder('${ f . alias } ')">Delete</button>
3892 </div>
3993 ` ) . join ( '' ) ;
4094 } catch ( error ) {
4195 console . error ( 'Error loading forwarders:' , error ) ;
42- }
43- }
44-
45- async function createForwarder ( event ) {
46- event . preventDefault ( ) ;
47-
48- const alias = document . getElementById ( 'alias' ) . value ;
49- const destination = document . getElementById ( 'destination' ) . value ;
50-
51- try {
52- const response = await fetch ( '/api/forwarders' , {
53- method : 'POST' ,
54- headers : {
55- 'Content-Type' : 'application/json' ,
56- } ,
57- body : JSON . stringify ( { alias, destination } )
58- } ) ;
59-
60- const result = await response . json ( ) ;
61- if ( result . success ) {
62- document . getElementById ( 'createForwarderForm' ) . reset ( ) ;
63- loadForwarders ( ) ;
64- } else {
65- alert ( 'Failed to create forwarder' ) ;
66- }
67- } catch ( error ) {
68- console . error ( 'Error creating forwarder:' , error ) ;
69- alert ( 'Error creating forwarder' ) ;
96+ document . getElementById ( 'forwardersList' ) . innerHTML = '<p class="error">Error loading forwarders</p>' ;
7097 }
7198}
7299
73100async function deleteForwarder ( alias ) {
74- if ( ! confirm ( `Delete forwarder ${ alias } ?` ) ) return ;
101+ if ( ! confirm ( `Are you sure you want to delete the forwarder "${ alias } "?` ) ) {
102+ return ;
103+ }
75104
76105 try {
77- const response = await fetch ( `/api/forwarders/${ alias } ` , {
106+ const response = await fetch ( `/api/forwarders/${ encodeURIComponent ( alias ) } ` , {
78107 method : 'DELETE'
79108 } ) ;
80109
81- const result = await response . json ( ) ;
82- if ( result . success ) {
110+ if ( response . ok ) {
83111 loadForwarders ( ) ;
84112 } else {
85113 alert ( 'Failed to delete forwarder' ) ;
86114 }
87115 } catch ( error ) {
88- console . error ( 'Error deleting forwarder :' , error ) ;
116+ console . error ( 'Error:' , error ) ;
89117 alert ( 'Error deleting forwarder' ) ;
90118 }
91119}
92120
93- async function toggle2FA ( ) {
94- const action = confirm ( 'Toggle 2FA status?' ) ;
95- if ( ! action ) return ;
121+ document . getElementById ( 'createForwarderForm' ) . addEventListener ( 'submit' , async ( e ) => {
122+ e . preventDefault ( ) ;
123+
124+ const alias = document . getElementById ( 'alias' ) . value ;
125+ const destinationSelect = document . getElementById ( 'destination' ) . value ;
126+ let destination ;
127+
128+ // Check if custom email is selected
129+ if ( destinationSelect === 'custom' ) {
130+ destination = document . getElementById ( 'customEmail' ) . value ;
131+ if ( ! destination ) {
132+ alert ( 'Please enter a custom email address' ) ;
133+ return ;
134+ }
135+ } else {
136+ destination = destinationSelect ;
137+ }
138+
139+ if ( ! destination ) {
140+ alert ( 'Please select or enter a destination email' ) ;
141+ return ;
142+ }
96143
97144 try {
98- const response = await fetch ( '/setup-2fa ' , {
145+ const response = await fetch ( '/api/forwarders ' , {
99146 method : 'POST' ,
100147 headers : {
101- 'Content-Type' : 'application/x-www-form-urlencoded ' ,
148+ 'Content-Type' : 'application/json ' ,
102149 } ,
103- body : 'enable=true'
150+ body : JSON . stringify ( { alias , destination } )
104151 } ) ;
105152
106- if ( response . redirected ) {
107- window . location . reload ( ) ;
153+ if ( response . ok ) {
154+ document . getElementById ( 'createForwarderForm' ) . reset ( ) ;
155+ document . getElementById ( 'customEmailGroup' ) . style . display = 'none' ;
156+ loadForwarders ( ) ;
108157 } else {
109- const data = await response . json ( ) ;
110- if ( data . qr_code ) {
111- document . getElementById ( 'qrCode' ) . innerHTML =
112- `<img src="data:image/png;base64,${ data . qr_code } " alt="QR Code">` ;
113- document . getElementById ( 'totpSecret' ) . textContent = data . secret ;
114- document . getElementById ( 'qrModal' ) . style . display = 'flex' ;
115- }
158+ alert ( 'Failed to create forwarder' ) ;
116159 }
117160 } catch ( error ) {
118- console . error ( 'Error toggling 2FA:' , error ) ;
161+ console . error ( 'Error:' , error ) ;
162+ alert ( 'Error creating forwarder' ) ;
119163 }
120- }
121-
122- function closeModal ( ) {
123- document . getElementById ( 'qrModal' ) . style . display = 'none' ;
124- window . location . reload ( ) ;
125- }
164+ } ) ;
126165
127166// Initialize
128167document . addEventListener ( 'DOMContentLoaded' , ( ) => {
129- if ( document . getElementById ( 'createForwarderForm' ) ) {
130- document . getElementById ( 'createForwarderForm' ) . addEventListener ( 'submit' , createForwarder ) ;
131- loadEmailAccounts ( ) ;
132- loadForwarders ( ) ;
168+ loadEmailAccounts ( ) ;
169+ loadForwarders ( ) ;
170+
171+ // Refresh forwarders every 60 seconds
172+ refreshInterval = setInterval ( loadForwarders , 60000 ) ;
173+ } ) ;
133174
134- // Refresh every 60 seconds
135- refreshInterval = setInterval ( loadForwarders , 60000 ) ;
175+ // Cleanup on page unload
176+ window . addEventListener ( 'beforeunload' , ( ) => {
177+ if ( refreshInterval ) {
178+ clearInterval ( refreshInterval ) ;
136179 }
137180} ) ;
0 commit comments