Commit Graph

6 Commits

Author SHA1 Message Date
Anso d5393a6027 refactor(frontend): extract useStackListState hook from EditorLayout (#901)
Moves the stack-list state cluster (14 useState calls, plus refs, memos,
effects, and 7 absorbed sub-hooks) into a new hook at
EditorLayout/hooks/useStackListState.ts, following the same pattern as
useEditorViewState (B4-5).

EditorLayout useState count: 42 -> 28. useEffect count unchanged.

Also fixes a stale-closure bug in isStackBusy: previously read from
stackActions state, making isBusy stale inside buildMenuCtx whenever
a stack action fired between dep-array updates. Now reads from
stackActionsRef.current so it is always current without needing to be
listed as a dep. Wrapping it in useCallback makes the function
reference stable.
2026-05-03 18:34:32 -04:00
Anso a85fbd5265 refactor(frontend): extract useEditorViewState hook from EditorLayout (#900)
Bundles 19 editor-view useState calls, 1 useRef, and 2 useEffects
(copiedDigest timer cleanup, logsMode localStorage persist) into a
co-located hook at EditorLayout/hooks/useEditorViewState.ts. EditorLayout
destructures the result so existing reference sites keep their bare
names. EditorView's prop interface is unchanged.

EditorLayout.tsx: 61 -> 42 useState, 21 -> 19 useEffect.

Adds 16 unit tests covering defaults, setters, logsMode hydrate/persist,
and copiedDigestTimerRef cleanup on unmount.

Behavior unchanged. Verified end-to-end in browser: stack switch
populates content/env/containers, edit mode toggles, .env tab swap
shows env content, Raw terminal logs button persists logsMode to
localStorage.
2026-05-03 18:00:11 -04:00
Anso ae3cc3f0fd refactor(frontend): extract EditorView from EditorLayout (#899)
Move the inline renderEditor JSX (~535 lines) out of EditorLayout.tsx
into a new EditorView component under components/EditorLayout/, matching
the pattern established by ViewRouter (B4-1) and CreateStackDialog
(B4-2). State ownership stays in EditorLayout for this PR; the next
step lifts state slices into a useEditorViewState hook.

The new file owns the compose-editor surface as a unit: command-center
identity card, action bar (Restart/Stop/Update + overflow with Rollback,
Scan config, Delete), per-container health strip with sparklines and
service action menus, the Logs section with Structured / Raw toggle,
and the right-column Monaco editor (when editingCompose) or
StackAnatomyPanel (default). Three module-level helpers
(extractUptime, healthcheckLabel, getStackStatePill) and the
ContainerInfo / StackAction types move with it; EditorLayout re-imports
the types so existing local consumers compile unchanged.

One small consolidation done in this PR: the trash-can onClick used to
call setStackToDelete(selectedFile) followed by
setDeleteDialogOpen(true). Those are wrapped into a single
requestDeleteStack callback owned by EditorLayout, exposed as one prop
on EditorView. The sidebar context-menu remove path remains unchanged
(it passes its own stackName to the setters).

EditorLayout.tsx: 2,747 -> 2,169 LOC (-578). Also drops ~25 imports
that were only consumed by the relocated block (Editor, Card*,
DropdownMenu*, Select*, Tabs*, Sparkline, StackAnatomyPanel,
StackFileExplorer, StructuredLogViewer, TerminalComponent,
ErrorBoundary, copyToClipboard, cn, springs, and 18 lucide icons).
EditorView.tsx: 822 LOC. Above the per-child < 500 target; further
sub-decomposition (CommandCenterCard, ContainerHealthStrip, etc.) is a
later step in the tracker, not this PR.
2026-05-03 15:32:26 -04:00
Anso b3382d07a1 refactor(frontend): extract dialog cluster from EditorLayout (#898)
Extract the two remaining inline ConfirmModal blocks at the bottom of
EditorLayout into their own modules under components/EditorLayout/,
matching the pattern established by CreateStackDialog (B4-2):

- DeleteStackDialog: takes open/onOpenChange/stackName/onConfirm; owns
  the prune-volumes checkbox state internally and resets it on close.
  EditorLayout's deleteStack handler now accepts pruneVolumes as a
  parameter instead of reading parent state.
- UnsavedChangesDialog: takes open/onCancel/onConfirm. The discard
  body is hoisted to a named handler in EditorLayout
  (discardAndLoadPending) so the dialog stays a thin presentational
  wrapper.

Also removes a dead label-bulk-action surface that had no live entry
point: bulkActionLabel and bulkAction were declared without setters,
and setBulkActionOpen(true) was never called from anywhere. The
multi-select bulk-stack-actions live elsewhere via useBulkStackActions
and SidebarBulkBar; this removed code was unrelated and unreachable.
Drops the BulkActionResult interface, four useState lines, the
bulkAffected useMemo, the runLabelBulkAction handler, and the inline
ConfirmModal.

EditorLayout.tsx: 2,852 -> 2,747 LOC (-105). useState count: 66 -> 61.
2026-05-03 14:56:55 -04:00
Anso 71b7a52def refactor(frontend): extract CreateStackDialog from EditorLayout (#895)
Continues the EditorLayout decomposition (B4-2). Pulls the inline
three-tab Create Stack dialog (Empty / From Git / From Docker Run) out
of EditorLayout into EditorLayout/CreateStackDialog.tsx.

Parent now owns only the open boolean and a domain callback pair;
all 14 form-state vars and 6 handlers move into the child. The slot
renders a thin trigger button plus the new dialog.

Metrics:
- EditorLayout.tsx: 3,266 -> 2,843 LOC
- new CreateStackDialog.tsx: 463 LOC (under the 500 ceiling)
- useState count in EditorLayout: 81 -> 66
2026-05-03 12:54:37 -04:00
Anso d203caf7dc refactor(frontend): extract ViewRouter from EditorLayout (#894)
Move the activeView switch from EditorLayout.tsx into a new
EditorLayout/ViewRouter.tsx covering the nine non-editor views
(settings, templates, resources, host-console, global-observability,
fleet, audit-log, auto-updates, scheduled-ops) plus the HomeDashboard
fall-through. The inline editor branch stays in EditorLayout via a
renderEditor render slot; it gets its own extraction in a follow-up.

EditorLayout shrinks from 3,356 to 3,266 LOC and sheds imports for
SettingsPage, AppStoreView, ResourcesView, HomeDashboard, AdmiralGate,
CapabilityGate, Skeleton, plus six lazy view declarations and the
inline ViewSkeleton helper. The lazy declarations move into ViewRouter;
SecurityHistoryView stays behind because it renders as a settings
overlay, not as a top-level tab.

ViewRouter introduces a small inline LazyView helper to deduplicate
the LazyBoundary + Suspense + ViewSkeleton triple-wrap that repeats
across six lazy views.

First step of the EditorLayout decomposition tracker.
2026-05-03 12:19:54 -04:00