Implementation:TobikoData Sqlmesh EnvironmentDetails
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, Environment_Management, Plan_Management |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
A React component that displays the environment selector, plan status, and change summary in the application header.
Description
EnvironmentDetails is a comprehensive React component that serves as the control center for SQLMesh environment and plan management in the UI. It displays the current environment, plan execution status, and pending changes in a compact header bar. The component orchestrates complex interactions between plan execution, environment selection, and status updates, managing multiple async API calls and state synchronization across various stores.
The component implements intelligent plan orchestration, automatically triggering plan runs when models change or environments switch, and managing the lifecycle of plan actions (running, applying, cancelling). It includes debounced status updates to prevent UI flickering during rapid state changes and handles multiple concurrent API fetching states. The component also provides a visual plan button with animated spinner that links to the plan page, showing real-time execution status.
Usage
Use this component in the application header or toolbar to provide users with environment context and plan management controls. It automatically manages plan execution and updates based on model changes and user interactions.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/library/components/environmentDetails/EnvironmentDetails.tsx
Signature
export default function EnvironmentDetails(): JSX.Element
Import
import EnvironmentDetails from '@components/environmentDetails/EnvironmentDetails'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| N/A | N/A | N/A | Component reads state from multiple context stores |
Outputs
| Name | Type | Description |
|---|---|---|
| JSX.Element | JSX.Element | The rendered environment details bar with controls |
Component Structure
The component renders different sections based on state:
Loading State
{isFetchingEnvironments ? (
<LoadingStatus>Loading Environments...</LoadingStatus>
) : (
// Main content
)}
Main Content
When loaded, displays three main sections:
- Plan Button/Status: Link to plan page with execution status
- Environment Selector: Dropdown to select/manage environments
- Environment Changes: Visual summary of pending changes
Plan Action Orchestration
Automatic Plan Execution
Plans automatically run when models or environment change:
useEffect(() => {
if (
models.size > 0 &&
isFalse(planAction.isProcessing) &&
isFalse(planAction.isRunningTask)
) {
resetPlanTrackers()
clearPlanApply()
void planRun()
}
}, [models, environment])
Triggers when:
- Models are available (models.size > 0)
- Plan is not currently processing
- No background tasks are running
Fetching State Tracking
Updates fetching flags when API calls start:
useEffect(() => {
if (isFetchingPlanRun) {
planOverview.isFetching = true
setPlanOverview(planOverview)
}
if (isFetchingPlanApply) {
planApply.isFetching = true
setPlanApply(planApply)
}
if (isFetchingPlanCancel) {
planCancel.isFetching = true
setPlanCancel(planCancel)
}
}, [isFetchingPlanRun, isFetchingPlanApply, isFetchingPlanCancel])
Plan Action State Management
Debounced updates to prevent flickering:
useEffect(() => {
clearTimeout(planActionUpdateTimeoutId)
const value = ModelPlanAction.getPlanAction({
planOverview,
planApply,
planCancel,
})
// Skip update if inconsistent or unchanged
if (
(value === EnumPlanAction.Done && planAction.isRunningTask) ||
value === planAction.value
)
return
// Debounce status updates
planActionUpdateTimeoutId = setTimeout(
() => {
setPlanAction(new ModelPlanAction({ value }))
planActionUpdateTimeoutId = undefined
},
includes(
[EnumPlanAction.Running, EnumPlanAction.RunningTask,
EnumPlanAction.Cancelling, EnumPlanAction.Applying],
value,
)
? 0 // Immediate for active states
: 500, // 500ms delay for completed states
) as unknown as number
}, [planOverview, planApply, planCancel])
Debounce strategy:
- Immediate (0ms): For Running, RunningTask, Cancelling, Applying
- Delayed (500ms): For Done and other completion states
This prevents flickering when state updates arrive rapidly.
Plan Button
The plan button shows different states based on plan action:
<ModuleLink
title={
planAction.isProcessing
? planAction.displayStatus(planOverview)
: 'Plan'
}
to={EnumRoutes.Plan}
icon={
planAction.isProcessing ? (
<Spinner variant={EnumVariant.Success} className="w-3 py-1" />
) : (
<OutlinePlayCircleIcon
className={clsx(
'w-5',
planOverview.isFailed
? 'text-danger-500 dark:text-danger-100'
: 'text-success-100',
)}
/>
)
}
className={clsx(
'px-2 rounded-full py-0.5 mr-1',
planOverview.isFailed
? 'bg-danger-10 dark:bg-danger-500'
: 'bg-success-500',
)}
/>
Plan Button States
| State | Icon | Color | Text |
|---|---|---|---|
| Processing | Spinner | Green | Status message (e.g., "Running plan...") |
| Success | Play icon | Green | "Plan" |
| Failed | Play icon | Red | "Plan" |
| Idle | Play icon | Green | "Plan" |
Environment Selector
<SelectEnvironment
className="border-none mx-2 w-full"
size={EnumSize.sm}
showAddEnvironment={true}
disabled={
isFetchingPlanRun ||
planAction.isProcessing ||
environment.isInitialProd
}
/>
Disabled Conditions
The selector is disabled when:
- isFetchingPlanRun: Plan is being fetched
- planAction.isProcessing: Plan is executing
- environment.isInitialProd: Initial production environment (cannot switch)
Conditional Rendering
The plan button only shows for certain module states:
{isFalse(modules.hasOnlyPlans) &&
isFalse(modules.hasOnlyPlansAndErrors) && (
<ModuleLink ... />
)}
Hidden when:
- Only plan data is available
- Only plan and error data is available
This prevents showing the plan button when the plan page is the only content.
API Integration
The component uses multiple API hooks:
const { isFetching: isFetchingPlanApply } = useApiPlanApply(environment.name)
const { isFetching: isFetchingPlanCancel } = useApiCancelPlan()
const { isFetching: isFetchingEnvironments } = useApiEnvironments()
const { refetch: planRun, isFetching: isFetchingPlanRun } = useApiPlanRun(
environment.name,
{
planOptions: { skip_tests: true, include_unmodified: true },
},
)
Plan Options
When running plans automatically:
- skip_tests: true - Skips test execution for faster feedback
- include_unmodified: true - Includes unchanged models in the plan
State Management
The component coordinates state across multiple stores:
- Context store: modules, environment, models
- Plan store: planAction, planApply, planOverview, planCancel
- API hooks: Fetching states for various operations
Timeout Management
The component uses a module-level timeout variable:
let planActionUpdateTimeoutId: Optional<number>
// Always clear before setting
clearTimeout(planActionUpdateTimeoutId)
// Set new timeout
planActionUpdateTimeoutId = setTimeout(...) as unknown as number
This ensures only one timeout is active at a time.