feat: redesign floating workspace interactions
This commit is contained in:
@@ -35,6 +35,7 @@ import { MapDevPanel } from "./components/map-dev-panel";
|
||||
import { MobileWorkbenchSheet } from "./components/mobile-workbench-sheet";
|
||||
import { FeaturePopover } from "./components/feature-popover";
|
||||
import { ScheduledConditionFeed } from "./components/scheduled-condition-feed";
|
||||
import { WorkbenchAgentPanels } from "./components/workbench-agent-panels";
|
||||
import {
|
||||
ToolbarPanel,
|
||||
type ExportViewPreset,
|
||||
@@ -44,7 +45,7 @@ import {
|
||||
import { WorkbenchTopBar } from "./components/workbench-top-bar";
|
||||
import {
|
||||
WorkbenchMainFrame,
|
||||
type WorkbenchNavigationSection
|
||||
type WorkbenchMainFrameHandle
|
||||
} from "./workspace/workbench-main-frame";
|
||||
import { WORKBENCH_SCENARIOS, WORKBENCH_USER } from "./data/workbench-session";
|
||||
import { useWorkbenchAgent } from "./hooks/use-workbench-agent";
|
||||
@@ -103,9 +104,8 @@ export function MapWorkbenchPage({
|
||||
const hasMapboxToken = Boolean(env.TJWATER_MAPBOX_ACCESS_TOKEN);
|
||||
const devPanelEnabled = env.TJWATER_ENABLE_DEV_PANEL;
|
||||
const mapContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const mainFrameRef = useRef<WorkbenchMainFrameHandle | null>(null);
|
||||
const [detailFeature, setDetailFeature] = useState<DetailFeature | null>(null);
|
||||
const [mainFrameSection, setMainFrameSection] = useState<WorkbenchNavigationSection>("agent");
|
||||
const [mainFrameNavigationCollapsed, setMainFrameNavigationCollapsed] = useState(false);
|
||||
const [devPanelOpen, setDevPanelOpen] = useState(false);
|
||||
const [impactVisible, setImpactVisible] = useState(false);
|
||||
const [activeToolId, setActiveToolId] = useState<ToolbarToolId | null>(null);
|
||||
@@ -154,6 +154,7 @@ export function MapWorkbenchPage({
|
||||
agentPanelWidth,
|
||||
closeMobileSheet,
|
||||
conditionFeedExpanded,
|
||||
conditionFeedMounted,
|
||||
handleConditionExpandedChange,
|
||||
isLargeScreen,
|
||||
leftPanelOpen,
|
||||
@@ -163,8 +164,11 @@ export function MapWorkbenchPage({
|
||||
openConditionFeedForViewport,
|
||||
rightPanelExpanded,
|
||||
rightPanelOpen,
|
||||
setAgentPanelWidth,
|
||||
setMobileSheetSnap,
|
||||
toggleConditionFeedForViewport
|
||||
shouldShowConditionFeed,
|
||||
toggleConditionFeedForViewport,
|
||||
viewportWidth
|
||||
} = useWorkbenchResponsiveLayout({
|
||||
activeToolOpen: activeToolId !== null,
|
||||
agentPanelOpen: agent.panelOpen,
|
||||
@@ -175,27 +179,14 @@ export function MapWorkbenchPage({
|
||||
});
|
||||
|
||||
function openAgentWorkspaceForViewport() {
|
||||
if (isLargeScreen) {
|
||||
setMainFrameSection("agent");
|
||||
setMainFrameNavigationCollapsed(false);
|
||||
}
|
||||
openAgentPanelForViewport();
|
||||
}
|
||||
|
||||
function openConditionWorkspaceForViewport() {
|
||||
if (isLargeScreen) {
|
||||
setMainFrameSection("conditions");
|
||||
setMainFrameNavigationCollapsed(false);
|
||||
}
|
||||
openConditionFeedForViewport();
|
||||
}
|
||||
|
||||
function toggleConditionWorkspaceForViewport() {
|
||||
if (isLargeScreen) {
|
||||
setMainFrameSection((current) => current === "conditions" ? "agent" : "conditions");
|
||||
setMainFrameNavigationCollapsed(false);
|
||||
return;
|
||||
}
|
||||
toggleConditionFeedForViewport();
|
||||
}
|
||||
|
||||
@@ -208,9 +199,9 @@ export function MapWorkbenchPage({
|
||||
const { controller: mapController, state: mapControllerState } = useWorkbenchMapController({
|
||||
mapRef,
|
||||
mapReady,
|
||||
leftPanelOpen: isLargeScreen ? false : leftPanelOpen,
|
||||
rightPanelOpen: isLargeScreen ? devPanelOpen : rightPanelOpen,
|
||||
conditionPanelExpanded: isLargeScreen ? false : rightPanelExpanded,
|
||||
leftPanelOpen,
|
||||
rightPanelOpen,
|
||||
conditionPanelExpanded: rightPanelExpanded,
|
||||
agentPanelWidth
|
||||
});
|
||||
|
||||
@@ -627,9 +618,9 @@ export function MapWorkbenchPage({
|
||||
zoom: trustedAction.zoom ?? Math.max(map.getZoom(), 14),
|
||||
padding: getResponsiveWorkbenchPadding(
|
||||
map,
|
||||
isLargeScreen ? false : leftPanelOpen,
|
||||
isLargeScreen ? devPanelOpen : rightPanelOpen,
|
||||
isLargeScreen ? false : rightPanelExpanded,
|
||||
leftPanelOpen,
|
||||
rightPanelOpen,
|
||||
rightPanelExpanded,
|
||||
agentPanelWidth
|
||||
),
|
||||
duration: trustedAction.durationMs ?? 500
|
||||
@@ -797,7 +788,7 @@ export function MapWorkbenchPage({
|
||||
activeScenarioId={activeScenarioId}
|
||||
alerts={workbenchAlerts}
|
||||
user={user}
|
||||
conditionFeedVisible={isLargeScreen ? mainFrameSection === "conditions" && !mainFrameNavigationCollapsed : mobileSheet === "condition"}
|
||||
conditionFeedVisible={isLargeScreen ? shouldShowConditionFeed : mobileSheet === "condition"}
|
||||
taskTickerAvailable={taskTickerAvailable}
|
||||
taskTickerVisible={taskTickerVisible}
|
||||
devPanelEnabled={devPanelEnabled}
|
||||
@@ -811,6 +802,7 @@ export function MapWorkbenchPage({
|
||||
onCompareScenario={handleCompareScenario}
|
||||
onExportScenarioReport={handleExportScenarioReport}
|
||||
onAnalyzeAlertsWithAgent={handleAnalyzeAlertsWithAgent}
|
||||
onCreateTestAnalysis={devPanelEnabled ? () => mainFrameRef.current?.openTestAnalysis() : undefined}
|
||||
onShowDataStatus={handleShowDataStatus}
|
||||
onRefreshTiles={handleRefreshTiles}
|
||||
onShowShortcuts={handleShowShortcuts}
|
||||
@@ -819,47 +811,7 @@ export function MapWorkbenchPage({
|
||||
/>
|
||||
|
||||
<WorkbenchMainFrame
|
||||
testEnabled={devPanelEnabled}
|
||||
activeSection={mainFrameSection}
|
||||
navigationCollapsed={mainFrameNavigationCollapsed}
|
||||
onActiveSectionChange={setMainFrameSection}
|
||||
onNavigationCollapsedChange={setMainFrameNavigationCollapsed}
|
||||
renderAgentPanel={(onCollapse) => (
|
||||
<AgentCommandPanel
|
||||
{...agentPanelProps}
|
||||
presentation="desktop-dock"
|
||||
onCollapse={onCollapse}
|
||||
/>
|
||||
)}
|
||||
conditionsPanel={(
|
||||
<ScheduledConditionFeed
|
||||
presentation="desktop-dock"
|
||||
conditions={scheduledConditions}
|
||||
expanded={conditionFeedExpanded}
|
||||
focusRequest={conditionFocusRequest}
|
||||
loading={scheduledConditionsLoading}
|
||||
visible
|
||||
selectedConditionId={selectedConditionId}
|
||||
onExpandedChange={handleConditionExpandedChange}
|
||||
onFocusRequestHandled={handleConditionFocusRequestHandled}
|
||||
onSelectedConditionChange={setSelectedConditionId}
|
||||
onExpandAgent={openAgentWorkspaceForViewport}
|
||||
onLoadHistorySession={handleLoadAgentHistorySession}
|
||||
onSubmitPrompt={agent.submitPrompt}
|
||||
/>
|
||||
)}
|
||||
layersPanel={(
|
||||
<div className="flex h-full min-h-0 flex-col gap-3 overflow-y-auto p-3">
|
||||
<MapToolbar items={toolbarItems} orientation="horizontal" className="w-full flex-wrap" />
|
||||
<ToolbarPanel {...toolbarPanelProps} panelWidthClassName="w-full" />
|
||||
</div>
|
||||
)}
|
||||
toolsPanel={(
|
||||
<div className="flex h-full min-h-0 flex-col gap-3 overflow-y-auto p-3">
|
||||
<MapToolbar items={toolbarItems} orientation="horizontal" className="w-full flex-wrap" />
|
||||
<ToolbarPanel {...toolbarPanelProps} panelWidthClassName="w-full" />
|
||||
</div>
|
||||
)}
|
||||
ref={mainFrameRef}
|
||||
mapContent={(
|
||||
<div
|
||||
ref={mapContainerRef}
|
||||
@@ -886,6 +838,39 @@ export function MapWorkbenchPage({
|
||||
)}
|
||||
/>
|
||||
|
||||
<WorkbenchAgentPanels
|
||||
panelProps={agentPanelProps}
|
||||
panelOpen={agent.panelOpen}
|
||||
panelCollapsing={agent.panelCollapsing}
|
||||
conditionExpanded={shouldShowConditionFeed && conditionFeedExpanded}
|
||||
personaState={agent.personaState}
|
||||
statusLabel={agent.statusLabel}
|
||||
viewportWidth={viewportWidth}
|
||||
onCollapsePanel={agent.collapsePanel}
|
||||
onExpandPanel={agent.expandPanel}
|
||||
onWidthCommit={setAgentPanelWidth}
|
||||
/>
|
||||
|
||||
{conditionFeedMounted && !devPanelOpen ? (
|
||||
<div className="absolute bottom-14 right-16 top-24 z-50 hidden lg:block 2xl:[--workbench-condition-width:var(--workbench-condition-width-wide)]">
|
||||
<ScheduledConditionFeed
|
||||
presentation="desktop-floating"
|
||||
conditions={scheduledConditions}
|
||||
expanded={conditionFeedExpanded}
|
||||
focusRequest={conditionFocusRequest}
|
||||
loading={scheduledConditionsLoading}
|
||||
visible={shouldShowConditionFeed}
|
||||
selectedConditionId={selectedConditionId}
|
||||
onExpandedChange={handleConditionExpandedChange}
|
||||
onFocusRequestHandled={handleConditionFocusRequestHandled}
|
||||
onSelectedConditionChange={setSelectedConditionId}
|
||||
onExpandAgent={openAgentWorkspaceForViewport}
|
||||
onLoadHistorySession={handleLoadAgentHistorySession}
|
||||
onSubmitPrompt={agent.submitPrompt}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{devPanelEnabled && devPanelOpen ? (
|
||||
<MapDevPanel
|
||||
commands={mapController}
|
||||
|
||||
Reference in New Issue
Block a user