mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-27 18:57:09 +00:00
feat(ui): Phase 57 - remote context UX (Option A) + network layer fixes
Task 1 - Network layer fixes: - AppStoreView: replace raw fetch() with apiFetch() on /templates and /templates/deploy so x-node-id header is injected for proxy routing - GlobalObservabilityView: replace raw fetch() with apiFetch() on /stacks and /logs/global - HostConsole: append ?nodeId= to WebSocket URL so the upgrade handler correctly routes the PTY session to the active remote node Task 2 - Scoped context two-tier UX (Option A / Portainer-style): - EditorLayout: add a context pill in the top header bar showing the active node name (pulsing blue for remote, green for local) - HostConsole: header now reads "Host Console - [Node Name]" - ResourcesView: title now reads "Resources Hub - [Node Name]" for remote - GlobalObservabilityView: floating node badge in top-left corner for remote - AppStoreView: deploy sheet shows "Deploying to: [Node Name]" badge - SettingsModal: remote nodes only see System Limits + Developer tabs; global-only tabs (Account, Appearance, Notifications, Nodes) are hidden; header subtitle shows remote node name
This commit is contained in:
@@ -5,6 +5,7 @@ import { Input } from '@/components/ui/input';
|
||||
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||
import { RefreshCw, Download, Trash2, Search, Filter } from 'lucide-react';
|
||||
import { apiFetch } from '@/lib/api';
|
||||
import { useNodes } from '@/context/NodeContext';
|
||||
|
||||
|
||||
interface LogEntry {
|
||||
@@ -17,6 +18,7 @@ interface LogEntry {
|
||||
}
|
||||
|
||||
export function GlobalObservabilityView() {
|
||||
const { activeNode } = useNodes();
|
||||
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [allStacks, setAllStacks] = useState<string[]>([]);
|
||||
@@ -57,7 +59,7 @@ export function GlobalObservabilityView() {
|
||||
useEffect(() => {
|
||||
const fetchStacks = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/stacks');
|
||||
const res = await apiFetch('/stacks');
|
||||
if (res.ok) {
|
||||
const stacks: string[] = await res.json();
|
||||
setAllStacks(stacks.sort());
|
||||
@@ -111,7 +113,7 @@ export function GlobalObservabilityView() {
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const logsRes = await fetch('/api/logs/global');
|
||||
const logsRes = await apiFetch('/logs/global');
|
||||
if (logsRes.ok) {
|
||||
setLogs(await logsRes.json());
|
||||
}
|
||||
@@ -180,6 +182,13 @@ export function GlobalObservabilityView() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full w-full relative group bg-[#0A0A0A] text-gray-300">
|
||||
{/* Node Context Indicator */}
|
||||
{activeNode?.type === 'remote' && (
|
||||
<div className="absolute top-2 left-4 z-10 flex items-center gap-1.5 bg-background/90 backdrop-blur-sm border border-border shadow-md rounded-md px-2.5 py-1 text-xs text-muted-foreground">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-blue-400 shrink-0" />
|
||||
{activeNode.name}
|
||||
</div>
|
||||
)}
|
||||
{/* Floating Action Bar */}
|
||||
<div className="absolute top-2 right-6 z-10 flex gap-2 transition-opacity duration-200 opacity-0 group-hover:opacity-100 focus-within:opacity-100 bg-background/90 backdrop-blur-sm border border-border shadow-md rounded-md p-1 pr-1">
|
||||
<div className="relative flex items-center">
|
||||
|
||||
Reference in New Issue
Block a user