mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-21 12:06:08 +00:00
feat(nodes): bulk panel self-update with live online indicator
Adds the ability to update node panels to the latest release from the Nodes page: select online, enabled nodes (checkboxes) and trigger their official self-updater, or use the per-row Update action. A node whose reported panel version trails the latest GitHub release is flagged with an 'update available' tag (compared via lib/panel-version, mirroring the Go isNewerVersion). Backend: Remote.UpdatePanel calls the node's existing POST /panel/api/server/updatePanel; NodeService.UpdatePanels fans out over the selected ids, skipping disabled/offline nodes with a per-node reason; exposed as POST /panel/api/nodes/updatePanel (documented in endpoints.ts + openapi.json). The bulk request sends a JSON body, so it sets Content-Type: application/json explicitly — axios defaults POST to form-urlencoded, which made ShouldBindJSON fail with 'invalid character i'. Also reuses the clients-page online cue on the Nodes page: a pulsing green dot plus green label for an online node. The .online-dot style moved to the shared styles/utils.css so both pages load it. Translations for all new node keys added across every language file.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
import { isPanelUpdateAvailable } from '@/lib/panel-version';
|
||||
|
||||
// Parity with web/service/panel.go isNewerVersion.
|
||||
describe('isPanelUpdateAvailable', () => {
|
||||
it('flags a strictly newer latest', () => {
|
||||
expect(isPanelUpdateAvailable('2.6.5', '2.6.4')).toBe(true);
|
||||
expect(isPanelUpdateAvailable('v2.7.0', 'v2.6.9')).toBe(true);
|
||||
expect(isPanelUpdateAvailable('3.0.0', '2.9.9')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when equal or the node is ahead', () => {
|
||||
expect(isPanelUpdateAvailable('2.6.4', '2.6.4')).toBe(false);
|
||||
expect(isPanelUpdateAvailable('v2.6.4', '2.6.4')).toBe(false);
|
||||
expect(isPanelUpdateAvailable('2.6.4', '2.6.5')).toBe(false);
|
||||
});
|
||||
|
||||
it('ignores a leading v on either side', () => {
|
||||
expect(isPanelUpdateAvailable('v2.6.5', '2.6.4')).toBe(true);
|
||||
expect(isPanelUpdateAvailable('2.6.5', 'v2.6.4')).toBe(true);
|
||||
});
|
||||
|
||||
it('never flags when a version is unknown', () => {
|
||||
expect(isPanelUpdateAvailable('', '2.6.4')).toBe(false);
|
||||
expect(isPanelUpdateAvailable('2.6.5', '')).toBe(false);
|
||||
});
|
||||
|
||||
it('falls back to string inequality for non-semver tags', () => {
|
||||
expect(isPanelUpdateAvailable('nightly-2', 'nightly-1')).toBe(true);
|
||||
expect(isPanelUpdateAvailable('nightly-1', 'nightly-1')).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user