feat(dashboard): native host onboarding when disconnected
CI / Build & Test (push) Successful in 3m19s
CI / Build & Test (push) Successful in 3m19s
- Add install-command helper (getInstallCommand + platform detection) with OS-specific one-liners and configurable base URL - Show onboarding card on Overview when !hostConnected: copy button, platform switcher (macOS/Linux / Windows), and "Check again" button - "Check again" triggers refresh and shows success/disconnected toast - refresh() returns state so callers can react to hostConnected - Add unit tests for install-commands (all platforms, base URL) - Document "Native host not found" flow in README and INSTALLATION
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
* Overview page — summary stats, quick-action cards, and virtualized connection lists.
|
||||
* Uses the OvList class for infinite-scroll, searchable tables of connections and servers.
|
||||
* Depends on: core/utils.js ($, escapeHtml), ui/state-tag.js (stateTag),
|
||||
* ui/modal.js (openModal), pages/ssh.js (openAddSshModal),
|
||||
* pages/rdp.js (openAddRdpModal), core/state.js (sshConnections, rdpConnections)
|
||||
* ui/modal.js (openModal), ui/toast.js (copyToClipboard, showToast),
|
||||
* pages/ssh.js (openAddSshModal), pages/rdp.js (openAddRdpModal),
|
||||
* core/state.js (sshConnections, rdpConnections), data/install-commands.js (getInstallCommand, detectPlatform, INSTALL_SCRIPT_BASE_URL)
|
||||
*/
|
||||
|
||||
const OV_PAGE = 20; // rows per page
|
||||
@@ -89,6 +90,22 @@ let _ovSvc = null;
|
||||
let _ovSsh = null;
|
||||
let _ovRdp = null;
|
||||
|
||||
/** Current platform for onboarding card (win32 | macos | linux). Set by detectPlatform or switcher. */
|
||||
let _onboardingPlatform = null;
|
||||
|
||||
/**
|
||||
* Update the onboarding card command and label for the given platform.
|
||||
* @param {'macos'|'linux'|'win32'} platform
|
||||
*/
|
||||
function _updateOnboardingCommand(platform) {
|
||||
if (typeof getInstallCommand === 'undefined' || typeof INSTALL_SCRIPT_BASE_URL === 'undefined') return;
|
||||
const { label, command } = getInstallCommand(INSTALL_SCRIPT_BASE_URL, platform);
|
||||
const labelEl = $('onboardingPlatformLabel');
|
||||
const cmdEl = $('onboardingCommand');
|
||||
if (labelEl) labelEl.textContent = label;
|
||||
if (cmdEl) cmdEl.textContent = command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and wire up the OvList instances for virtual hosts and server tunnels.
|
||||
* Called once during dashboard initialisation.
|
||||
@@ -188,6 +205,41 @@ function initOvLists() {
|
||||
$('qaAddSsh') ?.addEventListener('click', () => openAddSshModal(null));
|
||||
$('qaAddRdp') ?.addEventListener('click', () => openAddRdpModal(null));
|
||||
$('qaInstallCA') ?.addEventListener('click', () => openModal('modal-installCA'));
|
||||
|
||||
// Onboarding card (native host not found): Copy, Check again, platform switcher
|
||||
const copyBtn = $('onboardingCopyBtn');
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', () => {
|
||||
const cmdEl = $('onboardingCommand');
|
||||
if (cmdEl && typeof copyToClipboard === 'function') copyToClipboard(cmdEl.textContent, copyBtn);
|
||||
});
|
||||
}
|
||||
const checkAgainBtn = $('onboardingCheckAgainBtn');
|
||||
if (checkAgainBtn) {
|
||||
checkAgainBtn.addEventListener('click', async () => {
|
||||
if (typeof refresh !== 'function') return;
|
||||
const state = await refresh();
|
||||
if (state?.hostConnected) {
|
||||
if (typeof showToast === 'function') showToast('Native host connected', 'success');
|
||||
} else {
|
||||
if (typeof showToast === 'function') showToast('Still disconnected. Install the native host using the command above.', 'default');
|
||||
}
|
||||
});
|
||||
}
|
||||
const switchMacLinux = $('onboardingSwitchMacLinux');
|
||||
if (switchMacLinux) {
|
||||
switchMacLinux.addEventListener('click', () => {
|
||||
_onboardingPlatform = 'macos';
|
||||
_updateOnboardingCommand('macos');
|
||||
});
|
||||
}
|
||||
const switchWin = $('onboardingSwitchWin');
|
||||
if (switchWin) {
|
||||
switchWin.addEventListener('click', () => {
|
||||
_onboardingPlatform = 'win32';
|
||||
_updateOnboardingCommand('win32');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,6 +303,19 @@ function updateDashboard(state) {
|
||||
const lu = $('overviewLastUpdated');
|
||||
if (lu) lu.textContent = 'Updated ' + new Date().toLocaleTimeString();
|
||||
|
||||
// Onboarding card: show when native host is disconnected
|
||||
const onboardingEl = $('onboardingNativeHost');
|
||||
if (onboardingEl) {
|
||||
if (!state.hostConnected) {
|
||||
onboardingEl.style.display = 'block';
|
||||
if (_onboardingPlatform == null && typeof detectPlatform === 'function') _onboardingPlatform = detectPlatform();
|
||||
_updateOnboardingCommand(_onboardingPlatform || 'linux');
|
||||
} else {
|
||||
onboardingEl.style.display = 'none';
|
||||
_onboardingPlatform = null;
|
||||
}
|
||||
}
|
||||
|
||||
setText('swarmCount', servers.length);
|
||||
setText('connCount', virtualHosts.length);
|
||||
setText('serviceTunnelCount', serviceTunnels.length);
|
||||
|
||||
Reference in New Issue
Block a user