* Show traffic connection detail modal
(connDataStr)
| 16901 | if (!updateBtn) { |
| 16902 | return; |
| 16903 | } |
| 16904 | updateBtn.disabled = !!busy; |
| 16905 | updateBtn.className = busy |
| 16906 | ? 'w-full bg-gray-600 text-white py-2 px-4 rounded cursor-wait' |
| 16907 | : 'w-full bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded transition-colors'; |
| 16908 | updateElement('update-btn-text', label); |
| 16909 | }; |
| 16910 | |
| 16911 | try { |
| 16912 | setButtonState(true, 'Updating...'); |
| 16913 | addConsoleMessage(startMessage, 'info'); |
| 16914 | updateElement('update-info', 'Updating...'); |
| 16915 | |
| 16916 | const data = await postAPI(endpoint, {}); |
| 16917 | |
| 16918 | if (!data.success) { |
| 16919 | throw Object.assign(new Error(data.error || 'Update failed'), { payload: data }); |
| 16920 | } |
| 16921 | |
| 16922 | if (Array.isArray(data.warnings)) { |
| 16923 | data.warnings.forEach(w => addConsoleMessage(w, 'warning')); |
| 16924 | } |
| 16925 | addConsoleMessage(data.output || 'Update applied.', 'success'); |
| 16926 | if (data.requirements_changed) { |
| 16927 | addConsoleMessage('This update changes Python dependencies - installing them before the restart. This can take a few minutes.', 'info'); |
| 16928 | } |
| 16929 | if (data.local_changes_preserved && !data.local_changes_restored) { |
| 16930 | addConsoleMessage("Your local edits are saved in a git stash ('git stash list' to recover them).", 'warning'); |
| 16931 | } |
| 16932 | addConsoleMessage('System will restart automatically...', 'info'); |
| 16933 | updateElement('update-info', 'Update applied. Restarting...'); |
| 16934 | setButtonState(true, 'Restarting...'); |
| 16935 | |
| 16936 | setTimeout(() => { |
| 16937 | verifyServiceRestart(data.to_commit || ''); |
| 16938 | }, 5000); |
| 16939 | |
| 16940 | } catch (error) { |
| 16941 | console.error('Update error:', error); |
| 16942 | if (isLikelyNetworkError(error)) { |
| 16943 | // The service may have restarted before the response reached us - |
| 16944 | // verify the outcome instead of declaring failure. |
| 16945 | addConsoleMessage('Connection dropped while updating - verifying whether the update completed...', 'info'); |
| 16946 | updateElement('update-info', 'Connection dropped. Verifying update...'); |
| 16947 | setButtonState(true, 'Verifying...'); |
| 16948 | setTimeout(() => { |
| 16949 | verifyServiceRestart(''); |
| 16950 | }, 5000); |
| 16951 | return; |
| 16952 | } |
| 16953 | const payload = error.payload || { error: error.message }; |
| 16954 | if (payload.code === 'busy') { |
| 16955 | // Two tabs, two clicks. The other one is doing the work - follow it |
| 16956 | // rather than reporting a failure that did not happen. |
| 16957 | addConsoleMessage('An update is already running on this box - watching it instead.', 'info'); |
| 16958 | setButtonState(true, 'Updating...'); |
| 16959 | verifyServiceRestart(''); |
| 16960 | return; |
nothing calls this directly
no test coverage detected