From 53ccdac45f33a50d8457c7390d0b2489a7d6bcda Mon Sep 17 00:00:00 2001 From: Pulse Monitor Date: Thu, 14 Aug 2025 09:25:50 +0000 Subject: [PATCH] improve: enhance backup/restore UI with clearer password guidance - Add visual cards for export/import actions with descriptive icons - Allow users to use their login password by default for backups - Add option for custom passphrase when needed - Improve clarity around password requirements - Add security notice with clear guidance - Simplify the backup process by reducing password friction --- frontend-modern/src/components/Login.tsx | 37 ++-- .../src/components/Settings/Settings.tsx | 198 ++++++++++++++---- 2 files changed, 169 insertions(+), 66 deletions(-) diff --git a/frontend-modern/src/components/Login.tsx b/frontend-modern/src/components/Login.tsx index 98cf04b7e..ba2b6df49 100644 --- a/frontend-modern/src/components/Login.tsx +++ b/frontend-modern/src/components/Login.tsx @@ -47,27 +47,24 @@ export const Login: Component = (props) => { }; return ( -
+
-
-
-
-
- Pulse Logo -
+
+
+ Pulse Logo
-

- Welcome to Pulse +

+ Sign in to Pulse

- Enter your credentials to continue + Enter your credentials to access the dashboard

-
+
@@ -85,7 +82,7 @@ export const Login: Component = (props) => { type="text" autocomplete="username" required - class="appearance-none relative block w-full pl-10 pr-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400" + class="appearance-none relative block w-full pl-10 pr-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400" placeholder="Username" value={username()} onInput={(e) => setUsername(e.currentTarget.value)} @@ -106,7 +103,7 @@ export const Login: Component = (props) => { type="password" autocomplete="current-password" required - class="appearance-none relative block w-full pl-10 pr-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400" + class="appearance-none relative block w-full pl-10 pr-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400" placeholder="Password" value={password()} onInput={(e) => setPassword(e.currentTarget.value)} @@ -133,7 +130,7 @@ export const Login: Component = (props) => {
diff --git a/frontend-modern/src/components/Settings/Settings.tsx b/frontend-modern/src/components/Settings/Settings.tsx index 5e833bfbf..da000974d 100644 --- a/frontend-modern/src/components/Settings/Settings.tsx +++ b/frontend-modern/src/components/Settings/Settings.tsx @@ -128,6 +128,7 @@ const Settings: Component = () => { hasHTTPS: boolean; } | null>(null); const [exportPassphrase, setExportPassphrase] = createSignal(''); + const [useCustomPassphrase, setUseCustomPassphrase] = createSignal(false); const [importPassphrase, setImportPassphrase] = createSignal(''); const [importFile, setImportFile] = createSignal(null); const [showExportDialog, setShowExportDialog] = createSignal(false); @@ -541,12 +542,12 @@ const Settings: Component = () => { const handleExport = async () => { if (!exportPassphrase()) { - showError('Please enter a passphrase'); + showError(useCustomPassphrase() ? 'Please enter a passphrase' : 'Please enter your password'); return; } - if (exportPassphrase().length < 12) { - showError('Passphrase must be at least 12 characters long'); + if (useCustomPassphrase() && exportPassphrase().length < 12) { + showError('Custom passphrase must be at least 12 characters long'); return; } @@ -617,12 +618,7 @@ const Settings: Component = () => { const handleImport = async () => { if (!importPassphrase()) { - showError('Please enter the passphrase'); - return; - } - - if (importPassphrase().length < 12) { - showError('Passphrase must be at least 12 characters long'); + showError('Please enter the password'); return; } @@ -1575,19 +1571,78 @@ const Settings: Component = () => { {/* Backup & Restore */}

Backup & Restore

-
- - +

+ Securely backup your node configurations and credentials or restore from a previous backup +

+ +
+ {/* Export Section */} +
+
+
+ + + +
+
+

Export Configuration

+

+ Download an encrypted backup of all nodes and settings +

+ +
+
+
+ + {/* Import Section */} +
+
+
+ + + +
+
+

Restore Configuration

+

+ Upload a backup file to restore nodes and settings +

+ +
+
+
+
+ +
+
+ + + +
+

Security Notice

+
    +
  • • Backups contain encrypted credentials and sensitive data
  • +
  • • Use a strong passphrase (12+ characters recommended)
  • +
  • • Store backup files securely and never share the passphrase
  • +
+
+
@@ -1930,31 +1985,86 @@ const Settings: Component = () => {

Export Configuration

+ {/* Password Choice Section */} +
+
+ + + +
+
+ + {/* Show password input based on selection */}
setExportPassphrase(e.currentTarget.value)} - placeholder="Enter a strong passphrase" - class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100" + placeholder={useCustomPassphrase() ? "Enter a strong passphrase" : "Enter your Pulse login password"} + class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500" /> -

- Passphrase must be at least 12 characters. Required to import the configuration later. -

- -

- Passphrase too short: {exportPassphrase().length}/12 characters + +

+ Passphrase must be at least 12 characters. You'll need this to restore the backup. +

+ +

+ Passphrase too short: {exportPassphrase().length}/12 characters +

+
+
+ +

+ You'll use this same password when restoring the backup

-
-

- Security Note: The exported file will contain encrypted credentials. Keep it secure and remember your passphrase. -

+
+
+ + + +
+ Important: The backup file contains encrypted credentials. Store it securely and remember your {useCustomPassphrase() ? 'passphrase' : 'password'}. +
+
@@ -1962,6 +2072,7 @@ const Settings: Component = () => { onClick={() => { setShowExportDialog(false); setExportPassphrase(''); + setUseCustomPassphrase(false); }} class="px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700" > @@ -1969,7 +2080,7 @@ const Settings: Component = () => {