UI improvement: make edit and delete buttons visible for custom AI provider (#1535)

- Move edit and delete actions from hidden popover to visible buttons
- Restructure card layout: status badge and action buttons at top, title
below

<img width="1029" height="414" alt="image"
src="https://github.com/user-attachments/assets/60497f87-254e-4f4d-9f8c-ea73b8f2526e"
/>

closes #1358


    
<!-- This is an auto-generated description by cubic. -->
---

## Summary by cubic
Made edit and delete always visible on custom provider cards and
restructured the card layout for clearer actions and status. Improves
discoverability and aligns with #1358.

- **Refactors**
- Replaced popover menu with visible Edit and Delete icon buttons
(data-testid: edit-custom-provider, delete-custom-provider).
- Moved status badge and actions to the top; title now sits below;
badges don’t wrap.
- Updated e2e tests to use new buttons and adjusted selectors for the
updated heading.

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Adeniji Adekunle James
2025-10-15 00:58:09 +01:00
committed by GitHub
parent 0c4aef6f2c
commit d76f428447
4 changed files with 45 additions and 56 deletions

View File

@@ -3,10 +3,8 @@ import { test } from "./helpers/test_helper";
test("delete custom provider should not freeze", async ({ po }) => {
await po.setUp();
await po.goToSettingsTab();
await po.page.getByTestId("custom-provider-more-options").click();
await po.page.getByTestId("delete-custom-provider").click();
await po.page.getByRole("button", { name: "Delete Provider" }).click();
await po.page.getByRole("button", { name: "Delete Provider" }).click();
// Make sure UI hasn't freezed
await po.goToAppsTab();
});

View File

@@ -7,9 +7,7 @@ test("can edit custom provider", async ({ po }) => {
// Create a provider first
// Edit it
await po.page.getByTestId("custom-provider-more-options").click();
await po.page.getByRole("button", { name: "Edit Provider" }).click();
await po.page.getByTestId("edit-custom-provider").click();
await po.page.getByRole("textbox", { name: "Display Name" }).clear();
await po.page
.getByRole("textbox", { name: "Display Name" })

View File

@@ -776,9 +776,7 @@ export class PageObject {
}
async setUpTestModel() {
await this.page
.getByRole("heading", { name: "test-provider Needs Setup" })
.click();
await this.page.getByRole("heading", { name: "test-provider" }).click();
await this.page.getByRole("button", { name: "Add Custom Model" }).click();
await this.page
.getByRole("textbox", { name: "Model ID*" })

View File

@@ -10,17 +10,12 @@ import type { LanguageModelProvider } from "@/ipc/ipc_types";
import { useLanguageModelProviders } from "@/hooks/useLanguageModelProviders";
import { useCustomLanguageModelProvider } from "@/hooks/useCustomLanguageModelProvider";
import { GiftIcon, PlusIcon, MoreVertical, Trash2, Edit } from "lucide-react";
import { GiftIcon, PlusIcon, Trash2, Edit } from "lucide-react";
import { Skeleton } from "./ui/skeleton";
import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
import { AlertTriangle } from "lucide-react";
import { useState } from "react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Button } from "@/components/ui/button";
import {
AlertDialog,
@@ -32,6 +27,11 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { CreateCustomProviderDialog } from "./CreateCustomProviderDialog";
@@ -123,7 +123,42 @@ export function ProviderSettingsGrid() {
className="p-4 cursor-pointer"
onClick={() => handleProviderClick(provider.id)}
>
<CardTitle className="text-lg font-medium flex items-center justify-between mr-5">
{isCustom && (
<div
className="flex items-center justify-end"
onClick={(e) => e.stopPropagation()}
>
<Tooltip>
<TooltipTrigger asChild>
<Button
data-testid="edit-custom-provider"
variant="ghost"
size="sm"
className="h-8 w-8 p-0 hover:bg-muted rounded-md"
onClick={() => handleEditProvider(provider)}
>
<Edit className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Edit Provider</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
data-testid="delete-custom-provider"
variant="ghost"
size="sm"
className="h-8 w-8 p-0 text-destructive hover:text-destructive hover:bg-destructive/10 rounded-md"
onClick={() => setProviderToDelete(provider.id)}
>
<Trash2 className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Delete Provider</TooltipContent>
</Tooltip>
</div>
)}
<CardTitle className="text-lg font-medium mb-2">
{provider.name}
{isProviderSetup(provider.id) ? (
<span className="ml-3 text-sm font-medium text-green-500 bg-green-50 dark:bg-green-900/30 border border-green-500/50 dark:border-green-500/50 px-2 py-1 rounded-full">
@@ -144,46 +179,6 @@ export function ProviderSettingsGrid() {
)}
</CardDescription>
</CardHeader>
{isCustom && (
<div
className="absolute top-2 right-0"
onClick={(e) => e.stopPropagation()}
>
<Popover>
<PopoverTrigger asChild>
<Button
variant="ghost"
size="sm"
className="p-1 hover:bg-muted rounded-full focus:outline-none"
data-testid="custom-provider-more-options"
>
<MoreVertical className="h-4 w-4 text-muted-foreground" />
</Button>
</PopoverTrigger>
<PopoverContent align="end" className="w-48 p-2">
<Button
variant="ghost"
size="sm"
className="w-full justify-start mb-1"
onClick={() => handleEditProvider(provider)}
>
<Edit className="h-4 w-4 mr-2" />
Edit Provider
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start text-destructive hover:text-destructive hover:bg-destructive/10"
onClick={() => setProviderToDelete(provider.id)}
>
<Trash2 className="h-4 w-4 mr-2" />
Delete Provider
</Button>
</PopoverContent>
</Popover>
</div>
)}
</Card>
);
})}