Add instance heartbeat settings sidebar
This commit is contained in:
@@ -22,6 +22,7 @@ import { cn } from "../lib/utils";
|
||||
import { queryKeys } from "../lib/queryKeys";
|
||||
import { sidebarBadgesApi } from "../api/sidebarBadges";
|
||||
import { heartbeatsApi } from "../api/heartbeats";
|
||||
import { useLocation, useNavigate } from "@/lib/router";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -154,6 +155,10 @@ function SortableCompanyItem({
|
||||
export function CompanyRail() {
|
||||
const { companies, selectedCompanyId, setSelectedCompanyId } = useCompany();
|
||||
const { openOnboarding } = useDialog();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const isInstanceRoute = location.pathname.startsWith("/instance/");
|
||||
const highlightedCompanyId = isInstanceRoute ? null : selectedCompanyId;
|
||||
const sidebarCompanies = useMemo(
|
||||
() => companies.filter((company) => company.status !== "archived"),
|
||||
[companies],
|
||||
@@ -282,10 +287,15 @@ export function CompanyRail() {
|
||||
<SortableCompanyItem
|
||||
key={company.id}
|
||||
company={company}
|
||||
isSelected={company.id === selectedCompanyId}
|
||||
isSelected={company.id === highlightedCompanyId}
|
||||
hasLiveAgents={hasLiveAgentsByCompanyId.get(company.id) ?? false}
|
||||
hasUnreadInbox={hasUnreadInboxByCompanyId.get(company.id) ?? false}
|
||||
onSelect={() => setSelectedCompanyId(company.id)}
|
||||
onSelect={() => {
|
||||
setSelectedCompanyId(company.id);
|
||||
if (isInstanceRoute) {
|
||||
navigate(`/${company.issuePrefix}/dashboard`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</SortableContext>
|
||||
|
||||
21
ui/src/components/InstanceSidebar.tsx
Normal file
21
ui/src/components/InstanceSidebar.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Clock3, Settings } from "lucide-react";
|
||||
import { SidebarNavItem } from "./SidebarNavItem";
|
||||
|
||||
export function InstanceSidebar() {
|
||||
return (
|
||||
<aside className="w-60 h-full min-h-0 border-r border-border bg-background flex flex-col">
|
||||
<div className="flex items-center gap-2 px-3 h-12 shrink-0">
|
||||
<Settings className="h-4 w-4 text-muted-foreground shrink-0 ml-1" />
|
||||
<span className="flex-1 text-sm font-bold text-foreground truncate">
|
||||
Instance Settings
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<nav className="flex-1 min-h-0 overflow-y-auto scrollbar-auto-hide flex flex-col gap-4 px-3 py-2">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<SidebarNavItem to="/instance/settings" label="Heartbeats" icon={Clock3} />
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { BookOpen, Moon, Sun } from "lucide-react";
|
||||
import { Outlet, useLocation, useNavigate, useParams } from "@/lib/router";
|
||||
import { BookOpen, Moon, Settings, Sun } from "lucide-react";
|
||||
import { Link, Outlet, useLocation, useNavigate, useParams } from "@/lib/router";
|
||||
import { CompanyRail } from "./CompanyRail";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
import { InstanceSidebar } from "./InstanceSidebar";
|
||||
import { SidebarNavItem } from "./SidebarNavItem";
|
||||
import { BreadcrumbBar } from "./BreadcrumbBar";
|
||||
import { PropertiesPanel } from "./PropertiesPanel";
|
||||
@@ -42,6 +43,7 @@ export function Layout() {
|
||||
const { companyPrefix } = useParams<{ companyPrefix: string }>();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const isInstanceSettingsRoute = location.pathname.startsWith("/instance/");
|
||||
const onboardingTriggered = useRef(false);
|
||||
const lastMainScrollTop = useRef(0);
|
||||
const [mobileNavVisible, setMobileNavVisible] = useState(true);
|
||||
@@ -242,7 +244,7 @@ export function Layout() {
|
||||
>
|
||||
<div className="flex flex-1 min-h-0 overflow-hidden">
|
||||
<CompanyRail />
|
||||
<Sidebar />
|
||||
{isInstanceSettingsRoute ? <InstanceSidebar /> : <Sidebar />}
|
||||
</div>
|
||||
<div className="border-t border-r border-border px-3 py-2 bg-background">
|
||||
<div className="flex items-center gap-1">
|
||||
@@ -252,6 +254,18 @@ export function Layout() {
|
||||
icon={BookOpen}
|
||||
className="flex-1 min-w-0"
|
||||
/>
|
||||
<Button variant="ghost" size="icon-sm" className="text-muted-foreground shrink-0" asChild>
|
||||
<Link
|
||||
to="/instance/settings"
|
||||
aria-label="Instance settings"
|
||||
title="Instance settings"
|
||||
onClick={() => {
|
||||
if (isMobile) setSidebarOpen(false);
|
||||
}}
|
||||
>
|
||||
<Settings className="h-4 w-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
@@ -276,7 +290,7 @@ export function Layout() {
|
||||
sidebarOpen ? "w-60" : "w-0"
|
||||
)}
|
||||
>
|
||||
<Sidebar />
|
||||
{isInstanceSettingsRoute ? <InstanceSidebar /> : <Sidebar />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-r border-border px-3 py-2">
|
||||
@@ -287,6 +301,18 @@ export function Layout() {
|
||||
icon={BookOpen}
|
||||
className="flex-1 min-w-0"
|
||||
/>
|
||||
<Button variant="ghost" size="icon-sm" className="text-muted-foreground shrink-0" asChild>
|
||||
<Link
|
||||
to="/instance/settings"
|
||||
aria-label="Instance settings"
|
||||
title="Instance settings"
|
||||
onClick={() => {
|
||||
if (isMobile) setSidebarOpen(false);
|
||||
}}
|
||||
>
|
||||
<Settings className="h-4 w-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
|
||||
Reference in New Issue
Block a user