Skip to content

Conversation

@pujitm
Copy link
Member

@pujitm pujitm commented Jan 8, 2026

Summary

  • Added visual spinner indicator on container rows while start/stop operations are in progress

Test plan

  • Start a container - verify spinner shows during start
  • Stop a running container - verify spinner shows during stop
  • Start/stop multiple containers - verify each row shows appropriate indicators

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added loading indicator that displays when containers are busy or being updated.
  • Improvements

    • Enhanced container state detection for improved start/stop operation accuracy.
    • Extended auto-start configuration data retrieval for better container management.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 8, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

The changes add busy state tracking to the Docker container management UI by introducing an isBusy prop to DockerNameCell, updating the GraphQL query to include the autoStartWait field in container metadata, and modifying composables to compute and pass row-level busy state through the component hierarchy.

Changes

Cohort / File(s) Summary
Component Updates
web/src/components/Docker/DockerNameCell.vue, web/src/composables/useDockerTableColumns.ts
Added isBusy prop to DockerNameCell; updated icon rendering to display a spinning loader when busy or updating. Modified useDockerTableColumns to compute per-row busy state from busyRowIds and pass it as isBusy prop.
Container Action Logic
web/src/composables/useContainerActions.ts
Refactored handleRowStartStop to derive isRunning and isStarting flags from container state; reordered conditional logic to check isStarting for mutation path selection; aligned onWillStartContainers callback to trigger only during start operations.
GraphQL Query & Types
web/src/composables/docker-containers.query.ts, web/src/composables/gql/gql.ts, web/src/composables/gql/graphql.ts
Added autoStartWait field to meta section of organizer flatEntries in GetDockerContainers query. Extended gql function with type-safe overload for GetDockerContainers. Updated GetDockerContainersDocument to reflect new query structure and added default value for skipCache variable.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~10–15 minutes

Poem

🐰 A busy state now dances through the Docker shore,
Spinners twirl and loading shows what's planned before,
Auto-wait tracked kindly in GraphQL's embrace,
One hop, two hops, three—progress picks up pace!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: improving start/stop UX with visual feedback (spinners and delay badges), which is the core objective of the changeset.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25d804f and 6703d4a.

📒 Files selected for processing (5)
  • web/src/components/Docker/DockerNameCell.vue
  • web/src/composables/gql/gql.ts
  • web/src/composables/gql/graphql.ts
  • web/src/composables/useContainerActions.ts
  • web/src/composables/useDockerTableColumns.ts

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

❌ Patch coverage is 14.28571% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.47%. Comparing base (9ef1cf1) to head (6703d4a).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
web/src/components/Docker/DockerNameCell.vue 0.00% 7 Missing ⚠️
web/src/composables/useContainerActions.ts 0.00% 3 Missing ⚠️
web/src/composables/useDockerTableColumns.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1865      +/-   ##
==========================================
- Coverage   46.49%   46.47%   -0.02%     
==========================================
  Files         954      954              
  Lines       59788    59813      +25     
  Branches     5552     5557       +5     
==========================================
  Hits        27799    27799              
- Misses      31870    31895      +25     
  Partials      119      119              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25d804fb67

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 120 to 124
if (toStart.length) {
setRowsStarting?.(
toStart.map((i) => i.id),
false
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear starting flags even when batch mutations fail

The batch path marks rows as “starting” but only clears that state at the end of a successful run. If any stopMutation/startMutation rejects (e.g., a container fails to start), the function throws before hitting this reset, so startingRowIds stays set and the “Xs delay” badge can remain stuck until a full refresh. Wrapping the mutations in a try/finally (or clearing in the caller’s finally) would ensure the UI is restored after failures.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/composables/useContainerActions.ts (1)

81-126: Missing error handling will leave rows stuck in "starting" state.

The setRowsStarting cleanup (lines 120-125) executes only on success. If any mutation in the batch throws an error, the starting state persists indefinitely, leaving the UI in an inconsistent state.

🐛 Wrap cleanup in try/finally
 async function runStartStopBatch(
   toStart: { id: string; containerId: string; name: string }[],
   toStop: { id: string; containerId: string; name: string }[]
 ) {
   if (toStart.length) {
     onWillStartContainers?.(toStart);
     setRowsStarting?.(
       toStart.map((i) => i.id),
       true
     );
   }
-  const totalOps = toStop.length + toStart.length;
-  let completed = 0;
-  for (const item of toStop) {
-    completed++;
-    const isLast = completed === totalOps;
-    await stopMutation(
-      { id: item.containerId },
-      isLast
-        ? {
-            refetchQueries: [refetchQuery],
-            awaitRefetchQueries: true,
-          }
-        : { awaitRefetchQueries: false }
-    );
-  }
-  for (const item of toStart) {
-    completed++;
-    const isLast = completed === totalOps;
-    await startMutation(
-      { id: item.containerId },
-      isLast
-        ? {
-            refetchQueries: [refetchQuery],
-            awaitRefetchQueries: true,
-          }
-        : { awaitRefetchQueries: false }
-    );
-  }
-  if (toStart.length) {
-    setRowsStarting?.(
-      toStart.map((i) => i.id),
-      false
-    );
+  try {
+    const totalOps = toStop.length + toStart.length;
+    let completed = 0;
+    for (const item of toStop) {
+      completed++;
+      const isLast = completed === totalOps;
+      await stopMutation(
+        { id: item.containerId },
+        isLast
+          ? {
+              refetchQueries: [refetchQuery],
+              awaitRefetchQueries: true,
+            }
+          : { awaitRefetchQueries: false }
+      );
+    }
+    for (const item of toStart) {
+      completed++;
+      const isLast = completed === totalOps;
+      await startMutation(
+        { id: item.containerId },
+        isLast
+          ? {
+              refetchQueries: [refetchQuery],
+              awaitRefetchQueries: true,
+            }
+          : { awaitRefetchQueries: false }
+      );
+    }
+  } finally {
+    if (toStart.length) {
+      setRowsStarting?.(
+        toStart.map((i) => i.id),
+        false
+      );
+    }
   }
 }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ef1cf1 and 25d804f.

📒 Files selected for processing (5)
  • web/src/components/Docker/DockerContainersTable.vue
  • web/src/components/Docker/DockerNameCell.vue
  • web/src/components/Docker/docker-containers.query.ts
  • web/src/composables/useContainerActions.ts
  • web/src/composables/useDockerTableColumns.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Always use TypeScript imports with .js extensions for ESM compatibility
Never add comments unless they are needed for clarity of function
Never add comments for obvious things, and avoid commenting when starting and ending code blocks

Files:

  • web/src/composables/useDockerTableColumns.ts
  • web/src/composables/useContainerActions.ts
  • web/src/components/Docker/docker-containers.query.ts
web/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Always run pnpm codegen for GraphQL code generation in the web directory

Files:

  • web/src/composables/useDockerTableColumns.ts
  • web/src/composables/useContainerActions.ts
  • web/src/components/Docker/DockerContainersTable.vue
  • web/src/components/Docker/DockerNameCell.vue
  • web/src/components/Docker/docker-containers.query.ts
web/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)

Files:

  • web/src/composables/useDockerTableColumns.ts
  • web/src/composables/useContainerActions.ts
  • web/src/components/Docker/docker-containers.query.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Never use the any type. Always prefer proper typing
Avoid using casting whenever possible, prefer proper typing from the start

Files:

  • web/src/composables/useDockerTableColumns.ts
  • web/src/composables/useContainerActions.ts
  • web/src/components/Docker/docker-containers.query.ts
**/*

📄 CodeRabbit inference engine (.cursor/rules/default.mdc)

Never add comments unless they are needed for clarity of function

Files:

  • web/src/composables/useDockerTableColumns.ts
  • web/src/composables/useContainerActions.ts
  • web/src/components/Docker/DockerContainersTable.vue
  • web/src/components/Docker/DockerNameCell.vue
  • web/src/components/Docker/docker-containers.query.ts
web/**/*.query.ts

📄 CodeRabbit inference engine (CLAUDE.md)

GraphQL queries must be placed in .query.ts files

Files:

  • web/src/components/Docker/docker-containers.query.ts
web/**/*.{query.ts,mutation.ts}

📄 CodeRabbit inference engine (.cursor/rules/web-graphql.mdc)

All GraphQL under web/ must follow the .query.ts and .mutation.ts naming convention

Files:

  • web/src/components/Docker/docker-containers.query.ts
🧠 Learnings (1)
📚 Learning: 2025-07-24T18:48:44.035Z
Learnt from: mdatelle
Repo: unraid/api PR: 1533
File: web/components/Docker/Edit.vue:16-32
Timestamp: 2025-07-24T18:48:44.035Z
Learning: In web/components/Docker/Edit.vue, the hardcoded configuration values in the config ref are intentional temporary/dummy data used during initial UI development phase while building out the real Docker components, as clarified by mdatelle in PR #1533.

Applied to files:

  • web/src/components/Docker/DockerContainersTable.vue
🔇 Additional comments (11)
web/src/components/Docker/docker-containers.query.ts (1)

91-91: LGTM!

The addition of autoStartWait to the flatEntries meta section is consistent with the existing field in the containers query and properly supports the startup delay UI feature.

web/src/composables/useContainerActions.ts (2)

16-16: LGTM!

The optional setRowsStarting callback follows the same pattern as setRowsBusy and maintains backward compatibility.


162-194: LGTM!

The handleRowStartStop refactoring properly manages starting state with correct error handling via try/finally, ensuring the starting state is always cleared.

web/src/composables/useDockerTableColumns.ts (2)

29-29: LGTM!

The addition of startingRowIds to the options interface follows the existing pattern for busyRowIds and updatingRowIds.


90-108: LGTM!

The per-row state computation and propagation to DockerNameCell correctly threads through isRowBusy and isRowStarting flags, enabling the UI to reflect starting states.

web/src/components/Docker/DockerContainersTable.vue (3)

112-112: LGTM!

The startingRowIds reactive set follows the established pattern for tracking row states.


179-186: LGTM!

The setRowsStarting helper correctly manages the starting state set, mirroring the pattern used in setRowsBusy.


222-222: LGTM!

The wiring of setRowsStarting into useContainerActions and startingRowIds into useDockerTableColumns correctly connects the starting state management across the component hierarchy.

Also applies to: 391-391

web/src/components/Docker/DockerNameCell.vue (3)

13-14: LGTM!

The new isBusy and isStarting optional props are properly typed and enable the component to render appropriate visual feedback.


34-41: LGTM!

The autoStartWait and showDelayedBadge computed properties correctly derive the startup delay and determine when to display the delay badge.


87-109: LGTM!

The conditional rendering logic correctly prioritizes:

  1. Loading spinner during busy/updating states
  2. Startup delay badge during container start with configured delay
  3. Update available icon otherwise

This provides clear visual feedback for each operation state.

pujitm and others added 2 commits January 9, 2026 11:34
The autoStartWait delay only applies during boot/array start sequence,
not when manually starting containers from the UI. Showing a delay badge
during manual starts was misleading since no delay actually occurs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@pujitm pujitm merged commit c084e25 into main Jan 9, 2026
6 checks passed
@pujitm pujitm deleted the feat/clearer-docker-start-stop branch January 9, 2026 16:38
@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1865/dynamix.unraid.net.plg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants