diff --git a/backend/routes/cases/index.js b/backend/routes/cases/index.js index 6139440..9a87169 100644 --- a/backend/routes/cases/index.js +++ b/backend/routes/cases/index.js @@ -17,7 +17,7 @@ export default function (sequelize) { Tags.belongsToMany(Case, { through: 'caseTags', foreignKey: 'tagId', otherKey: 'caseId' }); router.get('/', verifySignedIn, verifyProjectVisibleFromFolderId, async (req, res) => { - const { folderId, title, priority, type, tag } = req.query; + const { folderId, search, priority, type, tag } = req.query; if (!folderId) { return res.status(400).json({ error: 'folderId is required' }); @@ -28,15 +28,18 @@ export default function (sequelize) { folderId: folderId, }; - if (title) { - const searchTerm = title.trim(); + if (search) { + const searchTerm = search.trim(); if (searchTerm.length > 100) { - return res.status(400).json({ error: 'too long title param' }); + return res.status(400).json({ error: 'too long search param' }); } if (searchTerm.length >= 1) { - whereClause[Op.or] = [{ title: { [Op.like]: `%${searchTerm}%` } }]; + whereClause[Op.or] = [ + { title: { [Op.like]: `%${searchTerm}%` } }, + { description: { [Op.like]: `%${searchTerm}%` } }, + ]; } } diff --git a/frontend/messages/en.json b/frontend/messages/en.json index fc4cbac..d94ee65 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -223,6 +223,7 @@ "no_cases_found": "No test cases found", "case_title": "Test Case Title", "case_description": "Test Case Description", + "case_title_or_description": "Test case title or description", "create": "Create", "please_enter": "Please enter test case title", "filter": "Filter", diff --git a/frontend/messages/ja.json b/frontend/messages/ja.json index 5b961d6..46d64e8 100644 --- a/frontend/messages/ja.json +++ b/frontend/messages/ja.json @@ -223,6 +223,7 @@ "no_cases_found": "テストケースがありません", "case_title": "テストケースタイトル", "case_description": "テストケース詳細", + "case_title_or_description": "テストケースのタイトルまたは説明", "create": "作成", "please_enter": "テストケースタイトルを入力してください", "filter": "フィルター", diff --git a/frontend/messages/pt-BR.json b/frontend/messages/pt-BR.json index 784f172..881c5ca 100644 --- a/frontend/messages/pt-BR.json +++ b/frontend/messages/pt-BR.json @@ -223,6 +223,7 @@ "no_cases_found": "Nenhum caso de teste encontrado", "case_title": "Título do Caso de Teste", "case_description": "Descrição do Caso de Teste", + "case_title_or_description": "Título ou descrição do caso de teste", "create": "Criar", "please_enter": "Por favor, insira o título do caso de teste", "filter": "Filtrar", diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CasesPane.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CasesPane.tsx index 3a28d36..fef0bc6 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CasesPane.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CasesPane.tsx @@ -34,7 +34,7 @@ export default function CasesPane({ }: Props) { const [cases, setCases] = useState([]); const [isCaseDialogOpen, setIsCaseDialogOpen] = useState(false); - const [titleFilter, setTitleFilter] = useState(''); + const [searchFilter, setSearchFilter] = useState(''); const [priorityFilter, setPriorityFilter] = useState([]); const [typeFilter, setTypeFilter] = useState([]); const [tagFilter, setTagFilter] = useState([]); @@ -45,13 +45,13 @@ export default function CasesPane({ const router = useRouter(); const searchParams = useSearchParams(); - const updateUrlParams = (updates: { title?: string; priority?: number[]; type?: number[]; tag?: number[] }) => { + const updateUrlParams = (updates: { search?: string; priority?: number[]; type?: number[]; tag?: number[] }) => { const currentParams = new URLSearchParams(searchParams.toString()); - if (updates.title) { - currentParams.set('title', updates.title); + if (updates.search) { + currentParams.set('search', updates.search); } else { - currentParams.delete('title'); + currentParams.delete('search'); } if (updates.priority && updates.priority.length > 0) { @@ -80,12 +80,12 @@ export default function CasesPane({ async function fetchDataEffect() { if (!context.isSignedIn()) return; - const titleParam = searchParams.get('title') || ''; + const searchParam = searchParams.get('search') || ''; const priorityParam = parseQueryParam(searchParams.get('priority')); const typeParam = parseQueryParam(searchParams.get('type')); const tagParam = parseQueryParam(searchParams.get('tag')); - setTitleFilter(titleParam); + setSearchFilter(searchParam); setPriorityFilter(priorityParam); setTypeFilter(typeParam); setTagFilter(tagParam); @@ -94,7 +94,7 @@ export default function CasesPane({ const data = await fetchCases( context.token.access_token, Number(folderId), - titleParam || undefined, + searchParam || undefined, priorityParam.length > 0 ? priorityParam : undefined, typeParam.length > 0 ? typeParam : undefined, tagParam.length > 0 ? tagParam : undefined @@ -143,12 +143,12 @@ export default function CasesPane({ await exportCases(context.token.access_token, Number(folderId), type); }; - const handleFilterChange = (title: string, priorities: number[], types: number[], tag: number[]) => { - setTitleFilter(title); + const handleFilterChange = (search: string, priorities: number[], types: number[], tag: number[]) => { + setSearchFilter(search); setPriorityFilter(priorities); setTypeFilter(types); setTagFilter(tag); - updateUrlParams({ title: title, priority: priorities, type: types, tag: tag }); + updateUrlParams({ search: search, priority: priorities, type: types, tag: tag }); }; // ************************************************************************** @@ -186,7 +186,7 @@ export default function CasesPane({ onDeleteCases={onDeleteCases} onExportCases={onExportCases} onFilterChange={handleFilterChange} - activeTitleFilter={titleFilter} + activeSearchFilter={searchFilter} activePriorityFilters={priorityFilter} activeTypeFilters={typeFilter} activeTagFilters={tagFilter} diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseFilter.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseFilter.tsx index d7c04e3..5c12f3b 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseFilter.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseFilter.tsx @@ -23,12 +23,12 @@ type TestCaseFilterProps = { messages: CasesMessages; priorityMessages: PriorityMessages; testTypeMessages: TestTypeMessages; - activeTitleFilter: string; + activeSearchFilter: string; activePriorityFilters: number[]; activeTypeFilters: number[]; activeTagFilters: number[]; projectId: string; - onFilterChange: (title: string, priorities: number[], types: number[], tags: number[]) => void; + onFilterChange: (search: string, priorities: number[], types: number[], tags: number[]) => void; }; type Tag = Pick; @@ -37,7 +37,7 @@ export default function TestCaseFilter({ messages, priorityMessages, testTypeMessages, - activeTitleFilter, + activeSearchFilter, activePriorityFilters, activeTypeFilters, activeTagFilters, @@ -45,7 +45,7 @@ export default function TestCaseFilter({ projectId, }: TestCaseFilterProps) { const tokenContext = useContext(TokenContext); - const [title, setTitle] = useState(''); + const [search, setSearch] = useState(''); const [selectedPriorities, setSelectedPriorities] = useState(new Set([])); const [selectedTypes, setSelectedTypes] = useState(new Set([])); const [selectedTags, setSelectedTags] = useState(new Set([])); @@ -74,8 +74,8 @@ export default function TestCaseFilter({ }, [activeTagFilters]); useEffect(() => { - setTitle(activeTitleFilter); - }, [activeTitleFilter]); + setSearch(activeSearchFilter); + }, [activeSearchFilter]); useEffect(() => { if (activePriorityFilters.length > 0) { @@ -125,7 +125,7 @@ export default function TestCaseFilter({ .filter((id) => !isNaN(id)); } - onFilterChange(title, priorityIndices, typeIndices, tagIds); + onFilterChange(search, priorityIndices, typeIndices, tagIds); }; const handleClearFilter = () => { @@ -137,7 +137,7 @@ export default function TestCaseFilter({ return (
-

{messages.caseTitle}

+

{messages.caseTitleOrDescription}

} type="search" - value={title} - onValueChange={setTitle} + value={search} + onValueChange={setSearch} maxLength={100} />
diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseTable.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseTable.tsx index 35f4b44..62e2a88 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseTable.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/TestCaseTable.tsx @@ -47,7 +47,7 @@ type Props = { onDeleteCases: (caseIds: number[]) => void; onExportCases: (type: string) => void; onFilterChange: (query: string, priorities: number[], types: number[], tag: number[]) => void; - activeTitleFilter: string; + activeSearchFilter: string; activePriorityFilters: number[]; activeTypeFilters: number[]; activeTagFilters: number[]; @@ -66,7 +66,7 @@ export default function TestCaseTable({ onDeleteCases, onExportCases, onFilterChange, - activeTitleFilter, + activeSearchFilter, activePriorityFilters, activeTypeFilters, activeTagFilters, @@ -105,7 +105,7 @@ export default function TestCaseTable({ > {highlightSearchTerm({ text: cellValue as string, - searchTerm: activeTitleFilter, + searchTerm: activeSearchFilter, })} ); @@ -147,7 +147,7 @@ export default function TestCaseTable({ } }, // eslint-disable-next-line react-hooks/exhaustive-deps - [activeTitleFilter] + [activeSearchFilter] ); // ************************************************************************** @@ -155,7 +155,7 @@ export default function TestCaseTable({ // ************************************************************************** const [showFilter, setShowFilter] = useState(false); const activeFilterNum = - (activeTitleFilter ? 1 : 0) + activePriorityFilters.length + activeTypeFilters.length + activeTagFilters.length; + (activeSearchFilter ? 1 : 0) + activePriorityFilters.length + activeTypeFilters.length + activeTagFilters.length; // ************************************************************************** // select test case @@ -318,7 +318,7 @@ export default function TestCaseTable({ messages={messages} priorityMessages={priorityMessages} testTypeMessages={testTypeMessages} - activeTitleFilter={activeTitleFilter} + activeSearchFilter={activeSearchFilter} activePriorityFilters={activePriorityFilters} activeTypeFilters={activeTypeFilters} activeTagFilters={activeTagFilters} diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx index 4f87d89..e67e174 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx @@ -31,6 +31,7 @@ export default function Page({ params }: { params: { projectId: string; folderId noCasesFound: t('no_cases_found'), caseTitle: t('case_title'), caseDescription: t('case_description'), + caseTitleOrDescription: t('case_title_or_description'), create: t('create'), pleaseEnter: t('please_enter'), apply: t('apply'), diff --git a/frontend/types/case.ts b/frontend/types/case.ts index 64cccad..b647534 100644 --- a/frontend/types/case.ts +++ b/frontend/types/case.ts @@ -79,6 +79,7 @@ type CasesMessages = { noCasesFound: string; caseTitle: string; caseDescription: string; + caseTitleOrDescription: string; create: string; pleaseEnter: string; filter: string; diff --git a/frontend/utils/caseControl.ts b/frontend/utils/caseControl.ts index 69b518f..a6b454d 100644 --- a/frontend/utils/caseControl.ts +++ b/frontend/utils/caseControl.ts @@ -29,15 +29,15 @@ async function fetchCase(jwt: string, caseId: number) { async function fetchCases( jwt: string, folderId: number, - title?: string, + search?: string, priority?: number[], type?: number[], tag?: number[] ) { const queryParams = [`folderId=${folderId}`]; - if (title) { - queryParams.push(`title=${title}`); + if (search) { + queryParams.push(`search=${search}`); } if (priority && priority.length > 0) {