Implementation:TobikoData Sqlmesh EnvironmentChanges
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, Plan_Management, Environment_Management |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
A React component that displays a visual summary of environment changes with categorized badges for added, modified, removed, and backfilled models.
Description
EnvironmentChanges is a sophisticated React component that provides a visual summary of pending changes in the current SQLMesh environment. It displays color-coded badges showing counts of different change types (added, directly modified, indirectly modified, metadata changes, removed, and backfills) and includes a refresh button to reload plan data. The component tracks changes using the ModelPlanOverviewTracker which preserves the last completed plan overview when new plans are being generated.
The component implements intelligent visibility logic, only displaying when there are changes to show or when the current plan is not the latest (indicating processing is in progress). The badges are organized in a horizontal group with overlapping styling that expands on hover, creating a compact yet informative visual representation. Each badge is clickable and shows a preview popover with detailed information about the changes in that category.
Usage
Use this component in the environment details bar to show users what changes are pending for the current environment. It automatically updates when plan data changes and provides quick access to change details through hover interactions.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/library/components/environmentDetails/EnvironmentChanges.tsx
Signature
export default function EnvironmentChanges(): JSX.Element
function ChangesToken({
className,
children,
}: {
className?: string
children: React.ReactNode
}): JSX.Element
Import
import EnvironmentChanges from '@components/environmentDetails/EnvironmentChanges'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| N/A | N/A | N/A | Component reads state from plan and context stores |
Outputs
| Name | Type | Description |
|---|---|---|
| JSX.Element | JSX.Element | The rendered changes summary or "No Changes" indicator |
Component Structure
The component renders different change badges in order:
- Added Models (green badge)
- Directly Modified Models (blue badge)
- Indirectly Modified Models (yellow badge)
- Metadata Changes (gray badge)
- Removed Models (red badge)
- Backfills (dark gray badge)
Badge Layout
<span className="flex group items-center bg-neutral-5 dark:bg-neutral-20 px-1 py-1 rounded-full">
{hasChanges && <ChangesToken>Changes</ChangesToken>}
{/* Added badge */}
<EnvironmentChangesPreview type={EnumPlanChangeType.Add} changes={added} />
{/* Direct modifications badge */}
<EnvironmentChangesPreview type={EnumPlanChangeType.Direct} changes={direct} />
{/* Indirect modifications badge */}
<EnvironmentChangesPreview type={EnumPlanChangeType.Indirect} changes={indirect} />
{/* Metadata changes badge */}
<EnvironmentChangesPreview type={EnumPlanChangeType.Metadata} changes={metadata} />
{/* Removed badge */}
<EnvironmentChangesPreview type={EnumPlanChangeType.Remove} changes={removed} />
{/* Backfills badge */}
<EnvironmentChangesPreview type={EnumPlanChangeType.Default} changes={backfills} />
</span>
Plan Overview Tracking
The component maintains a snapshot of the last completed plan:
const [planOverviewTracker, setPlanOverviewTracker] =
useState<ModelPlanOverviewTracker>(planOverview)
useEffect(() => {
if (isFalse(planOverview.isEmpty) && planOverview.isFinished) {
setPlanOverviewTracker(new ModelPlanOverviewTracker(planOverview))
}
}, [planOverview])
This ensures that change badges remain visible while a new plan is being generated.
Visibility Logic
The component shows when:
const shouldShow =
(isFalse(planOverview.isLatest) || planOverview.isFetching) &&
planOverviewTracker.hasUpdates
- Plan is not latest (new changes detected) OR plan is being fetched
- AND tracker has updates to show
Refresh Functionality
The ChangesToken includes a refresh button:
<Button
onClick={(e: MouseEvent) => {
e.stopPropagation()
void getEnvironments().then(({ data }) => {
void planRun()
updateEnvironments(data)
})
}}
>
<ArrowPathIcon className="text-neutral-500 w-4 h-4" />
</Button>
Clicking refresh:
- Fetches latest environment list
- Triggers a new plan run
- Updates the environment store with fresh data
Change Type Colors
| Change Type | Color | Description |
|---|---|---|
| Add | Green (success-500) | New models added to the environment |
| Direct | Blue (secondary-500) | Models with direct code changes |
| Indirect | Yellow (warning-500) | Models affected by upstream changes |
| Metadata | Gray (neutral-400) | Models with metadata-only changes |
| Remove | Red (danger-500) | Models removed from the environment |
| Backfills | Dark Gray (neutral-600) | Models requiring backfill operations |
Badge Overlap Behavior
The badges use negative margin to overlap:
className="-mr-2 group-hover:mr-0"
- Default state: Badges overlap with -2 margin
- Hover state: Group expands, removing overlap (mr-0)
This creates a compact display that expands for easier interaction.
No Changes State
When there are no changes, displays a simple token:
<ChangesToken className="pr-2 pl-0.5 py-1 rounded-full bg-neutral-5">
No Changes
</ChangesToken>