mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-22 03:04:03 +00:00
Update connection badge UI and add last update timestamp
- Make connection badge compact with hover animation - Show small icon (green/gray dot) that expands to show text on hover - Add smooth 500ms transition animation - Add last update timestamp to footer with static time display - Format timestamp as 12-hour time (e.g., "2:34:05 PM")
This commit is contained in:
+39
-10
@@ -84,12 +84,27 @@ function App() {
|
||||
const [dataUpdated, setDataUpdated] = createSignal(false);
|
||||
let updateTimeout: number;
|
||||
|
||||
// Last update time formatting
|
||||
const [lastUpdateText, setLastUpdateText] = createSignal('');
|
||||
|
||||
const formatLastUpdate = (timestamp: string) => {
|
||||
if (!timestamp) return '';
|
||||
const date = new Date(timestamp);
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: true
|
||||
});
|
||||
};
|
||||
|
||||
// Flash indicator when data updates
|
||||
createEffect(() => {
|
||||
// Watch for state changes
|
||||
const updateTime = state().lastUpdate;
|
||||
if (updateTime && updateTime !== '') {
|
||||
setDataUpdated(true);
|
||||
setLastUpdateText(formatLastUpdate(updateTime));
|
||||
window.clearTimeout(updateTimeout);
|
||||
updateTimeout = window.setTimeout(() => setDataUpdated(false), POLLING_INTERVALS.DATA_FLASH);
|
||||
}
|
||||
@@ -478,6 +493,7 @@ function App() {
|
||||
connected={connected}
|
||||
reconnecting={reconnecting}
|
||||
dataUpdated={dataUpdated}
|
||||
lastUpdateText={lastUpdateText}
|
||||
versionInfo={versionInfo}
|
||||
darkMode={darkMode}
|
||||
toggleDarkMode={toggleDarkMode}
|
||||
@@ -519,6 +535,7 @@ function AppLayout(props: {
|
||||
connected: () => boolean;
|
||||
reconnecting: () => boolean;
|
||||
dataUpdated: () => boolean;
|
||||
lastUpdateText: () => string;
|
||||
versionInfo: () => VersionInfo | null;
|
||||
darkMode: () => boolean;
|
||||
toggleDarkMode: () => void;
|
||||
@@ -623,16 +640,16 @@ function AppLayout(props: {
|
||||
</button>
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class={`status text-xs px-2 py-1 rounded-full flex items-center gap-1 ${
|
||||
class={`group status text-xs rounded-full flex items-center justify-center transition-all duration-500 ease-in-out px-1.5 ${
|
||||
props.connected()
|
||||
? 'connected bg-green-200 dark:bg-green-700 text-green-700 dark:text-green-300'
|
||||
? 'connected bg-green-200 dark:bg-green-700 text-green-700 dark:text-green-300 min-w-6 h-6 group-hover:px-3'
|
||||
: props.reconnecting()
|
||||
? 'reconnecting bg-yellow-200 dark:bg-yellow-700 text-yellow-700 dark:text-yellow-300'
|
||||
: 'disconnected bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
|
||||
? 'reconnecting bg-yellow-200 dark:bg-yellow-700 text-yellow-700 dark:text-yellow-300 py-1'
|
||||
: 'disconnected bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 min-w-6 h-6 group-hover:px-3'
|
||||
}`}
|
||||
>
|
||||
<Show when={props.reconnecting()}>
|
||||
<svg class="animate-spin h-3 w-3" fill="none" viewBox="0 0 24 24">
|
||||
<svg class="animate-spin h-3 w-3 flex-shrink-0" fill="none" viewBox="0 0 24 24">
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
@@ -648,11 +665,19 @@ function AppLayout(props: {
|
||||
></path>
|
||||
</svg>
|
||||
</Show>
|
||||
{props.connected()
|
||||
? 'Connected'
|
||||
: props.reconnecting()
|
||||
? 'Reconnecting...'
|
||||
: 'Disconnected'}
|
||||
<Show when={props.connected()}>
|
||||
<span class="h-2.5 w-2.5 rounded-full bg-green-600 dark:bg-green-400 flex-shrink-0"></span>
|
||||
</Show>
|
||||
<Show when={!props.connected() && !props.reconnecting()}>
|
||||
<span class="h-2.5 w-2.5 rounded-full bg-gray-600 dark:bg-gray-400 flex-shrink-0"></span>
|
||||
</Show>
|
||||
<span class={`whitespace-nowrap overflow-hidden transition-all duration-500 ${props.connected() || (!props.connected() && !props.reconnecting()) ? 'max-w-0 group-hover:max-w-[100px] group-hover:ml-2 group-hover:mr-1 opacity-0 group-hover:opacity-100' : 'max-w-[100px] ml-1 opacity-100'}`}>
|
||||
{props.connected()
|
||||
? 'Connected'
|
||||
: props.reconnecting()
|
||||
? 'Reconnecting...'
|
||||
: 'Disconnected'}
|
||||
</span>
|
||||
</div>
|
||||
<Show when={props.hasAuth() && !props.needsAuth()}>
|
||||
<Show when={props.proxyAuthInfo()?.username}>
|
||||
@@ -843,6 +868,10 @@ function AppLayout(props: {
|
||||
</a>
|
||||
{props.versionInfo()?.isDevelopment && ' (Development)'}
|
||||
{props.versionInfo()?.isDocker && ' - Docker'}
|
||||
<Show when={props.lastUpdateText()}>
|
||||
<span class="mx-2">|</span>
|
||||
<span>Last updated: {props.lastUpdateText()}</span>
|
||||
</Show>
|
||||
</footer>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user