mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
feat(ui): add pulse effect to connection indicator
This commit is contained in:
@@ -1,27 +0,0 @@
|
|||||||
import {cn} from "@/lib/utils";
|
|
||||||
|
|
||||||
export type ConnectionCircleProps = {
|
|
||||||
date?: Date | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConnectionCircle = ({date}: ConnectionCircleProps) => {
|
|
||||||
let style = "bg-gray-300 border-gray-400";
|
|
||||||
|
|
||||||
if (date instanceof Date && !isNaN(date.getTime())) {
|
|
||||||
const now = Date.now();
|
|
||||||
const timestamp = date.getTime();
|
|
||||||
const interval_seconds = (now - timestamp) / 1000;
|
|
||||||
|
|
||||||
if (interval_seconds < 55) {
|
|
||||||
style = "bg-green-400 border-green-600";
|
|
||||||
} else if (interval_seconds <= 60) {
|
|
||||||
style = "bg-orange-400 border-orange-600";
|
|
||||||
} else {
|
|
||||||
style = "bg-red-400 border-red-600";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.warn("Invalid date passed to ConnectionCircle:", date);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className={cn("w-5 h-5 rounded-full border-4", style)}/>;
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export type ConnectionIndicatorProps = {
|
||||||
|
date?: Date | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ConnectionIndicator = ({ date }: ConnectionIndicatorProps) => {
|
||||||
|
let style = "bg-gray-300";
|
||||||
|
let active = false;
|
||||||
|
|
||||||
|
if (date instanceof Date && !isNaN(date.getTime())) {
|
||||||
|
const intervalSeconds = (Date.now() - date.getTime()) / 1000;
|
||||||
|
|
||||||
|
if (intervalSeconds < 55) {
|
||||||
|
style = "bg-green-500";
|
||||||
|
active = true;
|
||||||
|
} else if (intervalSeconds <= 60) {
|
||||||
|
style = "bg-orange-400";
|
||||||
|
} else {
|
||||||
|
style = "bg-red-500";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative w-4 h-4">
|
||||||
|
{active && (
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
"absolute -inset-0.25 rounded-full opacity-60 animate-ping",
|
||||||
|
style
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
animationDuration: "2s",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"relative w-4 h-4 rounded-full shadow-sm animate-pulse",
|
||||||
|
style
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
animationDuration: "2s",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -3,10 +3,10 @@
|
|||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {Card} from "@/components/ui/card";
|
import {Card} from "@/components/ui/card";
|
||||||
import {ConnectionCircle} from "@/components/wrappers/common/connection-circle";
|
import {ConnectionIndicator} from "@/components/wrappers/common/connection-indicator";
|
||||||
import {formatDateLastContact} from "@/utils/date-formatting";
|
import {formatDateLastContact} from "@/utils/date-formatting";
|
||||||
import {AgentWith} from "@/db/schema/08_agent";
|
import {AgentWith} from "@/db/schema/08_agent";
|
||||||
import {Activity, ChevronRight, Copy, Check, Fingerprint, Server, Database, ShieldCheck} from "lucide-react";
|
import {Activity, ChevronRight, Copy, Check, Fingerprint, Server, Database} from "lucide-react";
|
||||||
import {Badge} from "@/components/ui/badge";
|
import {Badge} from "@/components/ui/badge";
|
||||||
import {truncateWords} from "@/utils/text";
|
import {truncateWords} from "@/utils/text";
|
||||||
import {useIsMobile} from "@/hooks/use-mobile";
|
import {useIsMobile} from "@/hooks/use-mobile";
|
||||||
@@ -86,7 +86,7 @@ export const AgentCard = (props: agentCardProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="scale-110">
|
<div className="scale-110">
|
||||||
<ConnectionCircle date={agent.lastContact}/>
|
<ConnectionIndicator date={agent.lastContact}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ChevronRight className="w-5 h-5 text-muted-foreground group-hover:text-primary group-hover:translate-x-1 transition-all" />
|
<ChevronRight className="w-5 h-5 text-muted-foreground group-hover:text-primary group-hover:translate-x-1 transition-all" />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Link from "next/link";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import {Card} from "@/components/ui/card";
|
import {Card} from "@/components/ui/card";
|
||||||
import {ConnectionCircle} from "@/components/wrappers/common/connection-circle";
|
import {ConnectionIndicator} from "@/components/wrappers/common/connection-indicator";
|
||||||
import {formatDateLastContact} from "@/utils/date-formatting";
|
import {formatDateLastContact} from "@/utils/date-formatting";
|
||||||
import {Database} from "@/db/schema/07_database";
|
import {Database} from "@/db/schema/07_database";
|
||||||
import {ChevronRight, Activity, Fingerprint, Copy, Check} from "lucide-react";
|
import {ChevronRight, Activity, Fingerprint, Copy, Check} from "lucide-react";
|
||||||
@@ -60,7 +60,7 @@ export const DatabaseCard = (props: databaseCardProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-end gap-3">
|
<div className="flex flex-col items-end gap-3">
|
||||||
<div className="scale-100 origin-right">
|
<div className="scale-100 origin-right">
|
||||||
<ConnectionCircle date={database.lastContact}/>
|
<ConnectionIndicator date={database.lastContact}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user