fix: scope environments "Test provider" button to clicked row (#8380)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents run inside environments, and the Environments settings page lets users configure each environment and verify it with a "Test provider" / "Test connection" button per row > - When a user clicked one environment's test button, every environment row's button switched to the disabled "Testing..." state at the same time, then all flipped back together > - That happened because all rows read the same shared `environmentProbeMutation.isPending` flag, so a single in-flight probe disabled and relabeled every button > - This is confusing: it looks like every environment is being tested, and it blocks interacting with other rows while one probe runs > - This pull request tracks the specific environment id being probed in dedicated state and scopes the disabled/label logic to that id > - The benefit is that only the button the user actually clicked shows "Testing..." and is disabled, while the other rows stay interactive ## Linked Issues or Issue Description No public GitHub issue exists, so the bug is described inline below following the bug report template. ### What happened? On the Environments settings page, clicking "Test provider" on one environment caused the test button on *every* environment row to change to "Testing..." and become disabled at the same time, then all reverted together when the probe finished. ### Expected behavior Only the button for the environment the user clicked should show "Testing..." and be disabled while its probe runs. Every other row's button should stay enabled and unchanged. ### Steps to reproduce 1. Open instance settings → Environments with two or more configured environments. 2. Click "Test provider" / "Test connection" on a single row. 3. Observe that all rows' buttons enter the "Testing..." disabled state simultaneously instead of just the clicked one. ### Paperclip version or commit `master` at commit a10f17800 (branch `fix/environments-test-provider-button-scope`). ### Deployment mode Local dev (`pnpm dev`). UI-only; reproduces independent of backend. ## What Changed - Added a dedicated `testingEnvironmentId` state in `ui/src/pages/CompanyEnvironments.tsx` to track which environment is currently being probed. - Set it in the probe mutation's `onMutate` and clear it in `onSettled`, and reset it when the selected company changes. - Scoped the test button's `disabled` state and `"Testing..."` label to `testingEnvironmentId === environment.id` instead of the shared `environmentProbeMutation.isPending` flag. - Added `ui/src/pages/CompanyEnvironments.test.tsx` verifying that clicking one environment's test button puts only that row into the "Testing..." disabled state while other rows stay enabled. ## Verification - `pnpm typecheck` (UI) passes clean. - `vitest run src/pages/CompanyEnvironments.test.tsx` passes (new test fails against the old shared-`isPending` behavior, confirming it guards the fix). - Manual: on the Environments page with multiple environments, click one row's test button and confirm only that button shows "Testing..." / is disabled while the others remain enabled, then it reverts on completion. ## Risks - Low risk. Single-file UI change scoped to per-row button state; no API, schema, or behavior changes to the probe itself. The probe mutation still runs identically — only which buttons reflect the pending state changed. ## Model Used - Claude Opus 4.8 (Anthropic), `claude-opus-4-8`, with extended reasoning and tool use, via Claude Code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge
This commit is contained in:
@@ -166,6 +166,7 @@ export function CompanyEnvironments() {
|
||||
const [editingEnvironmentId, setEditingEnvironmentId] = useState<string | null>(null);
|
||||
const [environmentForm, setEnvironmentForm] = useState<EnvironmentFormState>(createEmptyEnvironmentForm);
|
||||
const [probeResults, setProbeResults] = useState<Record<string, EnvironmentProbeResult | null>>({});
|
||||
const [testingEnvironmentId, setTestingEnvironmentId] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumbs([
|
||||
@@ -232,6 +233,12 @@ export function CompanyEnvironments() {
|
||||
|
||||
const environmentProbeMutation = useMutation({
|
||||
mutationFn: async (environmentId: string) => await environmentsApi.probe(environmentId),
|
||||
onMutate: (environmentId) => {
|
||||
setTestingEnvironmentId(environmentId);
|
||||
},
|
||||
onSettled: (_probe, _error, environmentId) => {
|
||||
setTestingEnvironmentId((current) => (current === environmentId ? null : current));
|
||||
},
|
||||
onSuccess: (probe, environmentId) => {
|
||||
setProbeResults((current) => ({
|
||||
...current,
|
||||
@@ -287,6 +294,7 @@ export function CompanyEnvironments() {
|
||||
setEditingEnvironmentId(null);
|
||||
setEnvironmentForm(createEmptyEnvironmentForm());
|
||||
setProbeResults({});
|
||||
setTestingEnvironmentId(null);
|
||||
}, [selectedCompanyId]);
|
||||
|
||||
function handleEditEnvironment(environment: Environment) {
|
||||
@@ -530,9 +538,9 @@ export function CompanyEnvironments() {
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => environmentProbeMutation.mutate(environment.id)}
|
||||
disabled={environmentProbeMutation.isPending}
|
||||
disabled={testingEnvironmentId === environment.id}
|
||||
>
|
||||
{environmentProbeMutation.isPending
|
||||
{testingEnvironmentId === environment.id
|
||||
? "Testing..."
|
||||
: environment.driver === "ssh"
|
||||
? "Test connection"
|
||||
|
||||
Reference in New Issue
Block a user