Merge cloud venue biomes into dashboard weather and Emberwake biome chip.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
This commit is contained in:
@@ -12,7 +12,8 @@ import { SacredMotif } from '../Visual/sacredGeometry/motifs';
|
||||
import SetupBanner from '../SetupBanner';
|
||||
import { getSetupStatus } from '../../help/setupStatus';
|
||||
import { resolvePageWeather } from '../../help/pageWeather';
|
||||
import { mergeScoutBiomeWeather, type ScoutConstellationSnapshot } from '../../help/scoutBiomeWeather';
|
||||
import { mergeBiomeWeather, type CloudVenueSnapshot } from '../../help/cloudVenueBiomeWeather';
|
||||
import { type ScoutConstellationSnapshot } from '../../help/scoutBiomeWeather';
|
||||
import { isDashboardRoute } from '../../help/routeEffects';
|
||||
import { api } from '../../api/client';
|
||||
import { usePresence } from '../../context/PresenceContext';
|
||||
@@ -45,7 +46,9 @@ function operatorDeckId(pathname: string): string {
|
||||
return 'dashboard';
|
||||
}
|
||||
|
||||
const NAV_BASE = [
|
||||
type NavItem = { readonly to: string; readonly label: string; readonly icon: string; readonly glow?: boolean };
|
||||
|
||||
const NAV_BASE: readonly NavItem[] = [
|
||||
{ to: '/dashboard', label: 'Command Deck', icon: 'deck' },
|
||||
{ to: '/crucible', label: 'Crucible', icon: 'crucible' },
|
||||
{ to: '/activity', label: 'Activity Feed', icon: 'activity' },
|
||||
@@ -57,15 +60,15 @@ const NAV_BASE = [
|
||||
{ to: '/builds', label: 'Builds', icon: 'builds' },
|
||||
{ to: '/emberwake', label: 'Emberwake', icon: 'ember' },
|
||||
{ to: '/settings', label: 'Calibrate', icon: 'gear' },
|
||||
] as const;
|
||||
];
|
||||
|
||||
const SEER_NAV = { to: '/seer', label: 'Seer', icon: 'seer' } as const;
|
||||
const SEER_NAV: NavItem = { to: '/seer', label: 'Seer', icon: 'seer' };
|
||||
|
||||
function buildNav(aiControlEnabled: boolean) {
|
||||
function buildNav(aiControlEnabled: boolean): NavItem[] {
|
||||
if (!aiControlEnabled) {
|
||||
return [...NAV_BASE];
|
||||
}
|
||||
const items = [...NAV_BASE];
|
||||
const items: NavItem[] = [...NAV_BASE];
|
||||
const calibrateIdx = items.findIndex((i) => i.to === '/settings');
|
||||
items.splice(calibrateIdx, 0, SEER_NAV);
|
||||
return items;
|
||||
@@ -310,14 +313,18 @@ export default function Layout({ children }: LayoutProps) {
|
||||
if (latestMessage?.type !== 'scout_constellations') return null;
|
||||
return latestMessage.payload as ScoutConstellationSnapshot;
|
||||
}, [latestMessage]);
|
||||
const cloudBiome = useMemo(() => {
|
||||
if (latestMessage?.type !== 'cloud_venue_biomes') return null;
|
||||
return latestMessage.payload as CloudVenueSnapshot;
|
||||
}, [latestMessage]);
|
||||
const pageWeather = useMemo(() => {
|
||||
const base = resolvePageWeather(location.pathname);
|
||||
const path = location.pathname.split('?')[0].replace(/\/$/, '') || '/';
|
||||
if (path === '/emberwake' || path === '/spread' || path === '/dashboard' || path === '/agents') {
|
||||
return mergeScoutBiomeWeather(base, scoutBiome);
|
||||
return mergeBiomeWeather(base, scoutBiome, cloudBiome);
|
||||
}
|
||||
return base;
|
||||
}, [location.pathname, scoutBiome]);
|
||||
}, [location.pathname, scoutBiome, cloudBiome]);
|
||||
const showDeckEffects = isDashboardRoute(location.pathname);
|
||||
const moreActive = MOBILE_MORE.some((item) => location.pathname === item.to);
|
||||
const mobileShortLabel: Record<string, string> = {
|
||||
|
||||
@@ -15,6 +15,19 @@
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.emberwake-biome-chip {
|
||||
display: inline-block;
|
||||
margin: 0.5rem 0 0;
|
||||
padding: 0.2rem 0.55rem;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--neon-cyan, #00e8f5);
|
||||
border: 1px solid rgba(0, 232, 245, 0.35);
|
||||
border-radius: 999px;
|
||||
background: rgba(0, 232, 245, 0.08);
|
||||
}
|
||||
|
||||
.emberwake-section-title {
|
||||
margin: 0 0 0.35rem;
|
||||
font-size: 1.1rem;
|
||||
|
||||
@@ -25,6 +25,8 @@ import SupplyChainExportWizard from '../components/Emberwake/SupplyChainExportWi
|
||||
import SSMSpreadPanel from '../components/Emberwake/SSMSpreadPanel';
|
||||
import SubnetAutopsyCard from '../components/Atlas/SubnetAutopsyCard';
|
||||
import { parseSeerSubnetAutopsy } from '../help/subnetAutopsy';
|
||||
import { activeBiomeLabel, type CloudVenueSnapshot } from '../help/cloudVenueBiomeWeather';
|
||||
import type { ScoutConstellationSnapshot } from '../help/scoutBiomeWeather';
|
||||
import { HelpTip } from '../components/HelpTip';
|
||||
import './EmberwakePage.css';
|
||||
import '../components/Presence/Presence.css';
|
||||
@@ -74,6 +76,18 @@ export default function EmberwakePage() {
|
||||
|
||||
const pinned = useMemo(() => builds.filter((b) => b.pinned), [builds]);
|
||||
|
||||
const biomeLabel = useMemo(() => {
|
||||
let scout: ScoutConstellationSnapshot | null = null;
|
||||
let cloud: CloudVenueSnapshot | null = null;
|
||||
if (latestMessage?.type === 'scout_constellations') {
|
||||
scout = latestMessage.payload as ScoutConstellationSnapshot;
|
||||
}
|
||||
if (latestMessage?.type === 'cloud_venue_biomes') {
|
||||
cloud = latestMessage.payload as CloudVenueSnapshot;
|
||||
}
|
||||
return activeBiomeLabel(scout, cloud);
|
||||
}, [latestMessage]);
|
||||
|
||||
// Keep refs so `load` can read current pin values without listing them as deps.
|
||||
// Listing pinA/pinB as deps caused a cascade: load() → setPinA/setPinB →
|
||||
// re-render → new load reference → useEffect fires load() again (×N).
|
||||
@@ -242,6 +256,11 @@ export default function EmberwakePage() {
|
||||
<p className="page-subtitle">
|
||||
Tag install links, export lure kits, and track which campaigns convert — all from one desk.
|
||||
</p>
|
||||
{biomeLabel && (
|
||||
<p className="emberwake-biome-chip font-tech" data-testid="emberwake-biome-chip">
|
||||
Weather biome · {biomeLabel}
|
||||
</p>
|
||||
)}
|
||||
<p className="emberwake-hero-links form-hint">
|
||||
<a href={SPREAD_TECHNIQUES_DOC} target="_blank" rel="noreferrer">
|
||||
Spread techniques playbook
|
||||
|
||||
Reference in New Issue
Block a user