mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
feat(frontend): Tooltip for "suggested tasks" (#9447)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import { render, screen, waitFor, within } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Provider } from "react-redux";
|
||||
@@ -7,6 +7,21 @@ import { setupStore } from "test-utils";
|
||||
import { TaskSuggestions } from "#/components/features/home/tasks/task-suggestions";
|
||||
import { SuggestionsService } from "#/api/suggestions-service/suggestions-service.api";
|
||||
import { MOCK_TASKS } from "#/mocks/task-suggestions-handlers";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
// Mock the translation function
|
||||
vi.mock("react-i18next", async () => {
|
||||
const actual = await vi.importActual("react-i18next");
|
||||
return {
|
||||
...(actual as object),
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
i18n: {
|
||||
changeLanguage: () => new Promise(() => {}),
|
||||
},
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
const renderTaskSuggestions = () => {
|
||||
const RouterStub = createRoutesStub([
|
||||
@@ -93,4 +108,26 @@ describe("TaskSuggestions", () => {
|
||||
|
||||
expect(screen.queryByTestId("task-group-skeleton")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should render the tooltip button", () => {
|
||||
renderTaskSuggestions();
|
||||
const tooltipButton = screen.getByTestId("task-suggestions-info");
|
||||
expect(tooltipButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should have the correct aria-label", () => {
|
||||
renderTaskSuggestions();
|
||||
const tooltipButton = screen.getByTestId("task-suggestions-info");
|
||||
expect(tooltipButton).toHaveAttribute(
|
||||
"aria-label",
|
||||
"TASKS$TASK_SUGGESTIONS_INFO",
|
||||
);
|
||||
});
|
||||
|
||||
it("should render the info icon", () => {
|
||||
renderTaskSuggestions();
|
||||
const tooltipButton = screen.getByTestId("task-suggestions-info");
|
||||
const icon = tooltipButton.querySelector("svg");
|
||||
expect(icon).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaInfoCircle } from "react-icons/fa";
|
||||
import { TaskGroup } from "./task-group";
|
||||
import { useSuggestedTasks } from "#/hooks/query/use-suggested-tasks";
|
||||
import { TaskSuggestionsSkeleton } from "./task-suggestions-skeleton";
|
||||
import { cn } from "#/utils/utils";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
|
||||
interface TaskSuggestionsProps {
|
||||
filterFor?: string | null;
|
||||
@@ -23,7 +25,19 @@ export function TaskSuggestions({ filterFor }: TaskSuggestionsProps) {
|
||||
data-testid="task-suggestions"
|
||||
className={cn("flex flex-col w-full", !hasSuggestedTasks && "gap-6")}
|
||||
>
|
||||
<h2 className="heading">{t(I18nKey.TASKS$SUGGESTED_TASKS)}</h2>
|
||||
<div className="flex items-center gap-2">
|
||||
<h2 className="heading">{t(I18nKey.TASKS$SUGGESTED_TASKS)}</h2>
|
||||
<TooltipButton
|
||||
testId="task-suggestions-info"
|
||||
tooltip={t(I18nKey.TASKS$TASK_SUGGESTIONS_TOOLTIP)}
|
||||
ariaLabel={t(I18nKey.TASKS$TASK_SUGGESTIONS_INFO)}
|
||||
className="text-[#9099AC] hover:text-white"
|
||||
placement="bottom"
|
||||
tooltipClassName="max-w-[348px]"
|
||||
>
|
||||
<FaInfoCircle size={16} />
|
||||
</TooltipButton>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-6">
|
||||
{isLoading && <TaskSuggestionsSkeleton />}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tooltip } from "@heroui/react";
|
||||
import { Tooltip, TooltipProps } from "@heroui/react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { NavLink } from "react-router";
|
||||
import { cn } from "#/utils/utils";
|
||||
@@ -12,7 +12,9 @@ export interface TooltipButtonProps {
|
||||
ariaLabel: string;
|
||||
testId?: string;
|
||||
className?: React.HTMLAttributes<HTMLButtonElement>["className"];
|
||||
tooltipClassName?: React.HTMLAttributes<HTMLDivElement>["className"];
|
||||
disabled?: boolean;
|
||||
placement?: TooltipProps["placement"];
|
||||
}
|
||||
|
||||
export function TooltipButton({
|
||||
@@ -24,7 +26,9 @@ export function TooltipButton({
|
||||
ariaLabel,
|
||||
testId,
|
||||
className,
|
||||
tooltipClassName,
|
||||
disabled = false,
|
||||
placement = "right",
|
||||
}: TooltipButtonProps) {
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
if (onClick && !disabled) {
|
||||
@@ -118,7 +122,12 @@ export function TooltipButton({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip content={tooltip} closeDelay={100} placement="right">
|
||||
<Tooltip
|
||||
content={tooltip}
|
||||
closeDelay={100}
|
||||
placement={placement}
|
||||
className={tooltipClassName}
|
||||
>
|
||||
{content}
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -611,6 +611,8 @@ export enum I18nKey {
|
||||
REPOSITORY$SELECT_REPO = "REPOSITORY$SELECT_REPO",
|
||||
TASKS$SUGGESTED_TASKS = "TASKS$SUGGESTED_TASKS",
|
||||
TASKS$NO_TASKS_AVAILABLE = "TASKS$NO_TASKS_AVAILABLE",
|
||||
TASKS$TASK_SUGGESTIONS_INFO = "TASKS$TASK_SUGGESTIONS_INFO",
|
||||
TASKS$TASK_SUGGESTIONS_TOOLTIP = "TASKS$TASK_SUGGESTIONS_TOOLTIP",
|
||||
PAYMENT$SPECIFY_AMOUNT_USD = "PAYMENT$SPECIFY_AMOUNT_USD",
|
||||
GIT$BITBUCKET_TOKEN_HELP_LINK = "GIT$BITBUCKET_TOKEN_HELP_LINK",
|
||||
GIT$BITBUCKET_TOKEN_SEE_MORE_LINK = "GIT$BITBUCKET_TOKEN_SEE_MORE_LINK",
|
||||
|
||||
@@ -9775,6 +9775,38 @@
|
||||
"de": "Keine Aufgaben verfügbar",
|
||||
"uk": "Немає доступних завдань"
|
||||
},
|
||||
"TASKS$TASK_SUGGESTIONS_INFO": {
|
||||
"en": "Task suggestions information",
|
||||
"ja": "タスク提案情報",
|
||||
"zh-CN": "任务建议信息",
|
||||
"zh-TW": "任務建議資訊",
|
||||
"ko-KR": "작업 제안 정보",
|
||||
"no": "Oppgaveforslag informasjon",
|
||||
"it": "Informazioni sui suggerimenti di attività",
|
||||
"pt": "Informações de sugestões de tarefas",
|
||||
"es": "Información de sugerencias de tareas",
|
||||
"ar": "معلومات اقتراحات المهام",
|
||||
"fr": "Informations sur les suggestions de tâches",
|
||||
"tr": "Görev önerisi bilgileri",
|
||||
"de": "Aufgabenvorschlag-Informationen",
|
||||
"uk": "Інформація про пропозиції завдань"
|
||||
},
|
||||
"TASKS$TASK_SUGGESTIONS_TOOLTIP": {
|
||||
"en": "These are AI-curated task suggestions to help you get started with common development activities and best practices for your repository.",
|
||||
"ja": "これらは、リポジトリの一般的な開発活動とベストプラクティスを始めるのに役立つAIによってキュレーションされたタスク提案です。",
|
||||
"zh-CN": "这些是AI策划的任务建议,帮助您开始进行常见的开发活动和存储库的最佳实践。",
|
||||
"zh-TW": "這些是AI策劃的任務建議,幫助您開始進行常見的開發活動和存儲庫的最佳實踐。",
|
||||
"ko-KR": "이것은 저장소의 일반적인 개발 활동과 모범 사례를 시작할 수 있도록 도와주는 AI가 선별한 작업 제안입니다.",
|
||||
"no": "Dette er AI-kuraterte oppgaveforslag som hjelper deg å komme i gang med vanlige utviklingsaktiviteter og beste praksis for ditt depot.",
|
||||
"it": "Questi sono suggerimenti di attività curati dall'IA per aiutarti a iniziare con le attività di sviluppo comuni e le migliori pratiche per il tuo repository.",
|
||||
"pt": "Estas são sugestões de tarefas curadas por IA para ajudá-lo a começar com atividades de desenvolvimento comuns e melhores práticas para seu repositório.",
|
||||
"es": "Estas son sugerencias de tareas curadas por IA para ayudarte a comenzar con actividades de desarrollo comunes y mejores prácticas para tu repositorio.",
|
||||
"ar": "هذه اقتراحات مهام منسقة بواسطة الذكاء الاصطناعي لمساعدتك على البدء بأنشطة التطوير الشائعة وأفضل الممارسات لمستودعك.",
|
||||
"fr": "Ce sont des suggestions de tâches curées par l'IA pour vous aider à commencer avec les activités de développement courantes et les meilleures pratiques pour votre dépôt.",
|
||||
"tr": "Bunlar, deponuz için yaygın geliştirme faaliyetleri ve en iyi uygulamalarla başlamanıza yardımcı olmak için AI tarafından düzenlenmiş görev önerileridir.",
|
||||
"de": "Dies sind KI-kuratierte Aufgabenvorschläge, die Ihnen helfen, mit gängigen Entwicklungsaktivitäten und bewährten Praktiken für Ihr Repository zu beginnen.",
|
||||
"uk": "Це AI-курировані пропозиції завдань, які допоможуть вам розпочати з поширеними діяльностями розробки та найкращими практиками для вашого репозиторію."
|
||||
},
|
||||
"PAYMENT$SPECIFY_AMOUNT_USD": {
|
||||
"en": "Specify an amount in USD to add - min $10",
|
||||
"ja": "追加するUSD金額を指定してください - 最小$10",
|
||||
|
||||
Reference in New Issue
Block a user