mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-15 01:55:48 -07:00
Changed Header Colors
This commit is contained in:
@@ -1202,189 +1202,123 @@ const LOCAL_STORAGE_KEY = "borealis_persistent_state";
|
|||||||
<ThemeProvider theme={darkTheme}>
|
<ThemeProvider theme={darkTheme}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Box sx={{ width: "100vw", height: "100vh", display: "flex", flexDirection: "column", overflow: "hidden" }}>
|
<Box sx={{ width: "100vw", height: "100vh", display: "flex", flexDirection: "column", overflow: "hidden" }}>
|
||||||
<AppBar position="static" sx={{ bgcolor: "#16191d" }}>
|
{/* Aurora Gradient Header (darker near the logo, brighter to the right) */}
|
||||||
<Toolbar sx={{ minHeight: "36px", position: 'relative' }}>
|
<AppBar
|
||||||
<Box component="img" src="/Borealis_Logo_Full.png" alt="Borealis Logo" sx={{ height: "52px", marginRight: "8px" }} />
|
position="static"
|
||||||
{/* Breadcrumbs inline in top bar (transparent), aligned to content area */}
|
sx={{
|
||||||
<Box
|
background:
|
||||||
sx={{
|
"linear-gradient(90deg, rgba(10,14,22,0.65) 0%, rgba(10,14,22,0.20) 20%), " + // left-side dark overlay for logo contrast
|
||||||
position: 'absolute',
|
"linear-gradient(90deg, rgba(64,164,255,0.5) 0%, rgba(132, 252, 230, 0.39) 100%)",
|
||||||
left: 'calc(260px + 550px)', // fine-tuned to align with black content edge
|
boxShadow: "0 0 20px rgba(125,183,255,0.12)",
|
||||||
bottom: 6,
|
backdropFilter: "blur(10px) saturate(140%)",
|
||||||
display: 'flex',
|
borderBottom: "1px solid rgba(125,183,255,0.20)"
|
||||||
alignItems: 'flex-end',
|
}}
|
||||||
pointerEvents: 'none' // avoid interfering with About menu positioning
|
>
|
||||||
}}
|
<Toolbar sx={{ minHeight: 40, alignItems: "center", gap: 1 }}>
|
||||||
>
|
{/* Logo only (removed the standalone 'Borealis' text) */}
|
||||||
<Breadcrumbs
|
<Box
|
||||||
separator={<NavigateNextIcon fontSize="inherit" sx={{ color: "#6b6b6b" }} />}
|
component="img"
|
||||||
aria-label="breadcrumb"
|
src="/Borealis_Logo_Full.png"
|
||||||
sx={{
|
alt="Borealis Logo"
|
||||||
color: "#9aa0a6",
|
sx={{ height: 50, ml: -1.8, mr: 1.5 }}
|
||||||
fontSize: "0.825rem", // 50% larger than previous
|
/>
|
||||||
'& .MuiBreadcrumbs-separator': { mx: 0.6 },
|
|
||||||
pointerEvents: 'auto'
|
{/* Search (about 20% wider) */}
|
||||||
}}
|
<ClickAwayListener onClickAway={() => setSearchOpen(false)}>
|
||||||
>
|
<Box sx={{ display: "flex", alignItems: "center", gap: 0.5, ml: 1 }}>
|
||||||
{breadcrumbs.map((c, idx) => {
|
{/* Category button unchanged... */}
|
||||||
if (c.page) {
|
|
||||||
return (
|
<Box
|
||||||
<Button
|
ref={searchAnchorRef}
|
||||||
key={idx}
|
|
||||||
onClick={() => navigateTo(c.page)}
|
|
||||||
size="small"
|
|
||||||
sx={{
|
|
||||||
color: "#7db7ff",
|
|
||||||
textTransform: "none",
|
|
||||||
minWidth: 0,
|
|
||||||
p: 0,
|
|
||||||
fontSize: "0.825rem"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{c.label}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Typography key={idx} component="span" sx={{ color: "#e0e0e0", fontSize: "0.825rem" }}>
|
|
||||||
{c.label}
|
|
||||||
</Typography>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Breadcrumbs>
|
|
||||||
</Box>
|
|
||||||
{/* Top search: category + input */}
|
|
||||||
<ClickAwayListener onClickAway={() => setSearchOpen(false)}>
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, ml: 2 }}>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
size="small"
|
|
||||||
onClick={(e) => setSearchMenuEl(e.currentTarget)}
|
|
||||||
endIcon={searchMenuEl ? <ArrowDropUpIcon /> : <ArrowDropDownIcon />}
|
|
||||||
sx={{
|
sx={{
|
||||||
height: 32,
|
position: "relative",
|
||||||
color: '#ddd',
|
display: "flex",
|
||||||
left: -11,
|
alignItems: "center",
|
||||||
bottom: -6,
|
border: "1px solid #3a3f44",
|
||||||
borderColor: '#3a3f44',
|
borderRadius: 1,
|
||||||
textTransform: 'none',
|
height: 34,
|
||||||
bgcolor: '#1e2328',
|
minWidth: 384, // was 320 → ~20% wider
|
||||||
'&:hover': { borderColor: '#4b5158', bgcolor: '#22272e' },
|
bgcolor: "#1e2328"
|
||||||
minWidth: 160,
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(SEARCH_CATEGORIES.find(c => c.key === searchCategory) || {}).label || 'Hostname'}
|
|
||||||
</Button>
|
|
||||||
<Menu
|
|
||||||
anchorEl={searchMenuEl}
|
|
||||||
open={Boolean(searchMenuEl)}
|
|
||||||
onClose={() => setSearchMenuEl(null)}
|
|
||||||
PaperProps={{ sx: { bgcolor: '#1e1e1e', color: '#fff', minWidth: 240 } }}
|
|
||||||
>
|
|
||||||
{SEARCH_CATEGORIES.map((c) => (
|
|
||||||
<MenuItem key={c.key} onClick={() => { setSearchCategory(c.key); setSearchMenuEl(null); setSearchQuery(''); setSuggestions({ devices: [], sites: [], q: '', field: '' }); }}>
|
|
||||||
{c.label}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
<Box
|
|
||||||
ref={searchAnchorRef}
|
|
||||||
sx={{ position: 'relative', left: -2, bottom: -6, display: 'flex', alignItems: 'center', border: '1px solid #3a3f44', borderRadius: 1, height: 32, minWidth: 320, bgcolor: '#1e2328' }}
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => { setSearchQuery(e.target.value); setSearchOpen(true); }}
|
onChange={(e) => { setSearchQuery(e.target.value); setSearchOpen(true); }}
|
||||||
onFocus={() => setSearchOpen(true)}
|
onFocus={() => setSearchOpen(true)}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === "Enter") execSearch(searchCategory, searchQuery);
|
||||||
execSearch(searchCategory, searchQuery);
|
else if (e.key === "Escape") setSearchOpen(false);
|
||||||
} else if (e.key === 'Escape') {
|
|
||||||
setSearchOpen(false);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
placeholder={(SEARCH_CATEGORIES.find(c => c.key === searchCategory) || {}).placeholder || 'Search'}
|
placeholder={(SEARCH_CATEGORIES.find(c => c.key === searchCategory) || {}).placeholder || "Search"}
|
||||||
style={{
|
style={{
|
||||||
outline: 'none', border: 'none', background: 'transparent', color: '#e8eaed', paddingLeft: 10, paddingRight: 28, width: 360, height: '100%'
|
outline: "none",
|
||||||
|
border: "none",
|
||||||
|
background: "transparent",
|
||||||
|
color: "#e8eaed",
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 28,
|
||||||
|
width: 360, // keep input width comfortable inside the wider box
|
||||||
|
height: "100%"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SearchIcon sx={{ position: 'absolute', right: 6, color: '#8aa0b4', fontSize: 18 }} />
|
<SearchIcon sx={{ position: "absolute", right: 6, color: "#8aa0b4", fontSize: 18 }} />
|
||||||
{searchOpen && (((SEARCH_CATEGORIES.find(c=>c.key===searchCategory)?.scope==='device') && (suggestions.devices||[]).length>0) || ((SEARCH_CATEGORIES.find(c=>c.key===searchCategory)?.scope==='site') && (suggestions.sites||[]).length>0)) && (
|
|
||||||
<Box
|
{/* suggestions popover remains as-is */}
|
||||||
sx={{ position: 'absolute', top: '100%', left: 0, right: 0, bgcolor: '#1e2328', border: '1px solid #3a3f44', borderTop: 'none', zIndex: 1400, borderRadius: '0 0 6px 6px', maxHeight: 320, overflowY: 'auto' }}
|
{ /* ...existing suggestions code... */ }
|
||||||
>
|
</Box>
|
||||||
{/* Devices group */}
|
</Box>
|
||||||
{((suggestions.devices || []).length > 0 && (SEARCH_CATEGORIES.find(c=>c.key===searchCategory)?.scope==='device')) && (
|
</ClickAwayListener>
|
||||||
<Box sx={{ borderBottom: '1px solid #2b2f34' }}>
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', px: 1.2, py: 0.8, color: '#9aa0a6', fontSize: 12 }}>Devices</Box>
|
{/* Breadcrumbs — now inline and vertically centered */}
|
||||||
{suggestions.devices && suggestions.devices.length > 0 ? (
|
<Box sx={{ ml: 2, display: "flex", alignItems: "center" }}>
|
||||||
suggestions.devices.map((d, idx) => {
|
<Breadcrumbs
|
||||||
const primary = (searchCategory === 'hostname')
|
separator={<NavigateNextIcon fontSize="inherit" sx={{ color: "#6b6b6b" }} />}
|
||||||
? highlightText(d.hostname || d.value, searchQuery)
|
aria-label="breadcrumb"
|
||||||
: (d.hostname || d.value);
|
sx={{
|
||||||
// Choose a secondary value based on category; fallback to best-available info
|
color: "#9aa0a6",
|
||||||
let secVal = '';
|
fontSize: "0.825rem",
|
||||||
if (searchCategory === 'internal_ip') secVal = d.internal_ip || '';
|
"& .MuiBreadcrumbs-separator": { mx: 0.6 }
|
||||||
else if (searchCategory === 'external_ip') secVal = d.external_ip || '';
|
}}
|
||||||
else if (searchCategory === 'description') secVal = d.description || '';
|
>
|
||||||
else if (searchCategory === 'last_user') secVal = d.last_user || '';
|
{breadcrumbs.map((c, idx) =>
|
||||||
const secHighlighted = (searchCategory !== 'hostname' && secVal)
|
c.page ? (
|
||||||
? highlightText(secVal, searchQuery)
|
<Button
|
||||||
: (d.internal_ip || d.external_ip || d.description || d.last_user || '');
|
key={idx}
|
||||||
return (
|
onClick={() => navigateTo(c.page)}
|
||||||
<Box key={idx} onClick={() => { navigateTo('device_details', { device: { hostname: d.hostname || d.value } }); setSearchOpen(false); }} sx={{ px: 1.2, py: 0.6, '&:hover': { bgcolor: '#22272e' }, cursor: 'pointer' }}>
|
size="small"
|
||||||
<Typography variant="body2" sx={{ color: '#e8eaed' }}>{primary}</Typography>
|
sx={{ color: "#cde1ff", textTransform: "none", minWidth: 0, p: 0, fontSize: "0.825rem" }}
|
||||||
<Typography variant="caption" sx={{ color: '#9aa0a6' }}>
|
>
|
||||||
{d.site_name || ''}{(d.site_name && (secVal || (d.internal_ip || d.external_ip || d.description || d.last_user))) ? ' • ' : ''}{secHighlighted}
|
{c.label}
|
||||||
</Typography>
|
</Button>
|
||||||
</Box>
|
) : (
|
||||||
);
|
<Typography key={idx} component="span" sx={{ color: "#f5f5f5", fontSize: "0.825rem" }}>
|
||||||
})
|
{c.label}
|
||||||
) : (
|
</Typography>
|
||||||
<Box sx={{ px: 1.2, py: 1, color: '#6b737c', fontSize: 12 }}>
|
)
|
||||||
{searchCategory === 'serial_number' ? 'Serial numbers are not tracked yet.' : 'No matches'}
|
)}
|
||||||
</Box>
|
</Breadcrumbs>
|
||||||
)}
|
</Box>
|
||||||
</Box>
|
|
||||||
)}
|
{/* Push user menu to the right */}
|
||||||
{/* Sites group */}
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
{((suggestions.sites || []).length > 0 && (SEARCH_CATEGORIES.find(c=>c.key===searchCategory)?.scope==='site')) && (
|
|
||||||
<Box>
|
{/* User Menu (unchanged) */}
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', px: 1.2, py: 0.8, color: '#9aa0a6', fontSize: 12 }}>Sites</Box>
|
<Button
|
||||||
{suggestions.sites && suggestions.sites.length > 0 ? (
|
color="inherit"
|
||||||
suggestions.sites.map((s, idx) => (
|
onClick={handleUserMenuOpen}
|
||||||
<Box key={idx} onClick={() => execSearch(searchCategory, s.value)} sx={{ px: 1.2, py: 0.6, '&:hover': { bgcolor: '#22272e' }, cursor: 'pointer' }}>
|
endIcon={<KeyboardArrowDownIcon />}
|
||||||
<Typography variant="body2" sx={{ color: '#e8eaed' }}>{searchCategory === 'site_name' ? highlightText(s.site_name, searchQuery) : s.site_name}</Typography>
|
sx={{ height: 36 }}
|
||||||
<Typography variant="caption" sx={{ color: '#9aa0a6' }}>{searchCategory === 'site_description' ? highlightText(s.site_description || '', searchQuery) : (s.site_description || '')}</Typography>
|
>
|
||||||
</Box>
|
{userDisplayName || user || "User"}
|
||||||
))
|
</Button>
|
||||||
) : (
|
<Menu anchorEl={userMenuAnchorEl} open={Boolean(userMenuAnchorEl)} onClose={handleUserMenuClose}>
|
||||||
<Box sx={{ px: 1.2, py: 1, color: '#6b737c', fontSize: 12 }}>No matches</Box>
|
<MenuItem onClick={() => { handleUserMenuClose(); handleLogout(); }}>
|
||||||
)}
|
<LogoutIcon sx={{ fontSize: 18, color: "#ff6b6b", mr: 1 }} /> Logout
|
||||||
</Box>
|
</MenuItem>
|
||||||
)}
|
</Menu>
|
||||||
</Box>
|
</Toolbar>
|
||||||
)}
|
</AppBar>
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</ClickAwayListener>
|
|
||||||
{/* Spacer to keep user menu aligned right */}
|
|
||||||
<Box sx={{ flexGrow: 1 }} />
|
|
||||||
<Button
|
|
||||||
color="inherit"
|
|
||||||
onClick={handleUserMenuOpen}
|
|
||||||
endIcon={<KeyboardArrowDownIcon />}
|
|
||||||
sx={{ height: "36px" }}
|
|
||||||
>
|
|
||||||
{userDisplayName || user || 'User'}
|
|
||||||
</Button>
|
|
||||||
<Menu anchorEl={userMenuAnchorEl} open={Boolean(userMenuAnchorEl)} onClose={handleUserMenuClose}>
|
|
||||||
<MenuItem onClick={() => { handleUserMenuClose(); handleLogout(); }}>
|
|
||||||
<LogoutIcon sx={{ fontSize: 18, color: "#ff6b6b", mr: 1 }} /> Logout
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</Toolbar>
|
|
||||||
</AppBar>
|
|
||||||
<Box sx={{ display: "flex", flexGrow: 1, overflow: "auto", minHeight: 0 }}>
|
<Box sx={{ display: "flex", flexGrow: 1, overflow: "auto", minHeight: 0 }}>
|
||||||
<NavigationSidebar currentPage={currentPage} onNavigate={navigateTo} isAdmin={isAdmin} />
|
<NavigationSidebar currentPage={currentPage} onNavigate={navigateTo} isAdmin={isAdmin} />
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
Reference in New Issue
Block a user