Create delete run confirm dialog

This commit is contained in:
Takeshi Kimata
2024-05-26 21:17:41 +09:00
parent ff2d3a88e5
commit 1bab870239
8 changed files with 113 additions and 68 deletions

View File

@@ -0,0 +1,34 @@
import { Button, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@nextui-org/react';
type Props = {
isOpen: boolean;
onCancel: () => void;
onConfirm: () => void;
closeText: string;
confirmText: string;
deleteText: string;
};
export default function ProjectDialog({ isOpen, onCancel, onConfirm, closeText, confirmText, deleteText }: Props) {
return (
<Modal
isOpen={isOpen}
onOpenChange={() => {
onCancel();
}}
>
<ModalContent>
<ModalHeader className="flex flex-col gap-1">{deleteText}</ModalHeader>
<ModalBody>{confirmText}</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onCancel}>
{closeText}
</Button>
<Button color="danger" onPress={() => onConfirm()}>
{deleteText}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}

View File

@@ -207,7 +207,10 @@
"actions": "Actions", "actions": "Actions",
"new_run": "New Run", "new_run": "New Run",
"delete_run": "Delete Run", "delete_run": "Delete Run",
"no_runs_found": "No runs found" "no_runs_found": "No runs found",
"close": "Close",
"are_you_sure": "Are you sure you want to delete the run?",
"delete": "Delete"
}, },
"Run": { "Run": {
"back_to_runs": "Back to test runs", "back_to_runs": "Back to test runs",

View File

@@ -16,7 +16,7 @@
"organize_test_cases": "テストケースを整理とグラフィカルなテスト管理", "organize_test_cases": "テストケースを整理とグラフィカルなテスト管理",
"case_edit": "テストケース", "case_edit": "テストケース",
"case_home": "ダッシュボード", "case_home": "ダッシュボード",
"case_run": "テスト実行" "case_run": "テストラン"
}, },
"Header": { "Header": {
"title": "オープンソーステストケース管理ツール", "title": "オープンソーステストケース管理ツール",
@@ -89,12 +89,12 @@
"Project": { "Project": {
"home": "ホーム", "home": "ホーム",
"test_cases": "テストケース", "test_cases": "テストケース",
"test_runs": "テストの実行" "test_runs": "テストラン"
}, },
"Home": { "Home": {
"Folders": "フォルダー", "Folders": "フォルダー",
"test_cases": "テストケース", "test_cases": "テストケース",
"test_runs": "テスト実行", "test_runs": "テストラン",
"progress": "進捗", "progress": "進捗",
"untested": "未実行", "untested": "未実行",
"passed": "成功", "passed": "成功",
@@ -198,18 +198,21 @@
"max_file_size": "最大ファイルサイズ" "max_file_size": "最大ファイルサイズ"
}, },
"Runs": { "Runs": {
"run_list": "テストの実行一覧", "run_list": "テストラン一覧",
"id": "ID", "id": "ID",
"name": "名前", "name": "名前",
"description": "詳細", "description": "詳細",
"last_update": "最終更新", "last_update": "最終更新",
"actions": "アクション", "actions": "アクション",
"new_run": "新規テストの実行", "new_run": "新規テストラン",
"delete_run": "テストの実行を削除", "delete_run": "テストランを削除",
"no_runs_found": "テストの実行がありません" "no_runs_found": "テストランがありません",
"close": "閉じる",
"are_you_sure": "テストランを削除してもよろしいですか?",
"delete": "削除"
}, },
"Run": { "Run": {
"back_to_runs": "テストの実行一覧に戻る", "back_to_runs": "テストラン一覧に戻る",
"updating": "更新中...", "updating": "更新中...",
"update": "更新", "update": "更新",
"progress": "進捗", "progress": "進捗",
@@ -238,8 +241,8 @@
"skipped": "スキップ", "skipped": "スキップ",
"select_test_case": "テストケースを選択", "select_test_case": "テストケースを選択",
"test_case_selection": "テストケース選択", "test_case_selection": "テストケース選択",
"include_in_run": "テストの実行に含める", "include_in_run": "テストランに含める",
"exclude_from_run": "テストの実行から除外する", "exclude_from_run": "テストランから除外する",
"no_cases_found": "テストケースが見つかりません" "no_cases_found": "テストケースが見つかりません"
} }
} }

View File

@@ -1,35 +0,0 @@
'use client';
import { Button, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@nextui-org/react';
import { ProjectsMessages } from '@/types/project';
type Props = {
isOpen: boolean;
deleteProjectId: number | null;
onCancel: () => void;
onConfirm: (projectId: number | number) => {};
messages: ProjectsMessages;
};
export default function ProjectDialog({ isOpen, deleteProjectId, onCancel, onConfirm, messages }: Props) {
return (
<Modal
isOpen={isOpen}
onOpenChange={() => {
onCancel();
}}
>
<ModalContent>
<ModalHeader className="flex flex-col gap-1">{messages.delete}</ModalHeader>
<ModalBody>{messages.areYouSure}</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onCancel}>
{messages.close}
</Button>
<Button color="danger" onPress={() => onConfirm(deleteProjectId)}>
{messages.delete}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}

View File

@@ -7,7 +7,7 @@ import { ProjectType, ProjectsMessages } from '@/types/project';
import ProjectsTable from './ProjectsTable'; import ProjectsTable from './ProjectsTable';
import ProjectDialog from './ProjectDialog'; import ProjectDialog from './ProjectDialog';
import { fetchProjects, createProject, updateProject, deleteProject } from './projectsControl'; import { fetchProjects, createProject, updateProject, deleteProject } from './projectsControl';
import ProjectDeleteDialog from './ProjectDeleteDialog'; import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
export type Props = { export type Props = {
messages: ProjectsMessages; messages: ProjectsMessages;
@@ -47,11 +47,11 @@ export default function ProjectsPage({ messages, locale }: Props) {
setEditingProject(null); setEditingProject(null);
}; };
// delete dialog // delete confirm dialog
const [isDeleteProjectDialogOpen, setIsDeleteProjectDialogOpen] = useState(false); const [isDeleteConfirmDialogOpen, setIsDeleteConfirmDialogOpen] = useState(false);
const [deleteProjectId, setDeleteProjectId] = useState<number | null>(null); const [deleteProjectId, setDeleteProjectId] = useState<number | null>(null);
const closeDeleteDialog = () => { const closeDeleteConfirmDialog = () => {
setIsDeleteProjectDialogOpen(false); setIsDeleteConfirmDialogOpen(false);
setDeleteProjectId(null); setDeleteProjectId(null);
}; };
@@ -74,13 +74,15 @@ export default function ProjectsPage({ messages, locale }: Props) {
const onDeleteClick = (projectId: number) => { const onDeleteClick = (projectId: number) => {
setDeleteProjectId(projectId); setDeleteProjectId(projectId);
setIsDeleteProjectDialogOpen(true); setIsDeleteConfirmDialogOpen(true);
}; };
const onConfirm = async (projectId: number) => { const onConfirm = async () => {
await deleteProject(context.token.access_token, projectId); if (deleteProjectId) {
setProjects(projects.filter((project) => project.id !== projectId)); await deleteProject(context.token.access_token, deleteProjectId);
closeDeleteDialog(); setProjects(projects.filter((project) => project.id !== deleteProjectId));
closeDeleteConfirmDialog();
}
}; };
return ( return (
@@ -110,12 +112,13 @@ export default function ProjectsPage({ messages, locale }: Props) {
messages={messages} messages={messages}
/> />
<ProjectDeleteDialog <DeleteConfirmDialog
isOpen={isDeleteProjectDialogOpen} isOpen={isDeleteConfirmDialogOpen}
deleteProjectId={deleteProjectId} onCancel={closeDeleteConfirmDialog}
onCancel={closeDeleteDialog}
onConfirm={onConfirm} onConfirm={onConfirm}
messages={messages} closeText={messages.close}
confirmText={messages.areYouSure}
deleteText={messages.delete}
/> />
</div> </div>
); );

View File

@@ -5,6 +5,7 @@ import { Plus } from 'lucide-react';
import RunsTable from './RunsTable'; import RunsTable from './RunsTable';
import { fetchRuns, createRun, deleteRun } from './runsControl'; import { fetchRuns, createRun, deleteRun } from './runsControl';
import { RunsMessages } from '@/types/run'; import { RunsMessages } from '@/types/run';
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
type Props = { type Props = {
projectId: string; projectId: string;
@@ -15,6 +16,14 @@ type Props = {
export default function RunsPage({ projectId, locale, messages }: Props) { export default function RunsPage({ projectId, locale, messages }: Props) {
const [runs, setRuns] = useState([]); const [runs, setRuns] = useState([]);
// delete confirm dialog
const [isDeleteConfirmDialogOpen, setIsDeleteConfirmDialogOpen] = useState(false);
const [deleteRunId, setDeleteRunId] = useState<number | null>(null);
const closeDeleteConfirmDialog = () => {
setIsDeleteConfirmDialogOpen(false);
setDeleteRunId(null);
};
useEffect(() => { useEffect(() => {
async function fetchDataEffect() { async function fetchDataEffect() {
try { try {
@@ -39,13 +48,26 @@ export default function RunsPage({ projectId, locale, messages }: Props) {
} }
}; };
const onDeleteClick = async (runId: number) => { // const onDeleteClick = async (runId: number) => {
try { // try {
await deleteRun(runId); // await deleteRun(runId);
const data = await fetchRuns(projectId); // const data = await fetchRuns(projectId);
setRuns(data); // setRuns(data);
} catch (error: any) { // } catch (error: any) {
console.error('Error deleting run:', error); // console.error('Error deleting run:', error);
// }
// };
const onDeleteClick = (runId: number) => {
setDeleteRunId(runId);
setIsDeleteConfirmDialogOpen(true);
};
const onConfirm = async () => {
if (deleteRunId) {
await deleteRun(deleteRunId);
setRuns(runs.filter((run) => run.id !== deleteRunId));
closeDeleteConfirmDialog();
} }
}; };
@@ -61,6 +83,15 @@ export default function RunsPage({ projectId, locale, messages }: Props) {
</div> </div>
<RunsTable projectId={projectId} runs={runs} onDeleteRun={onDeleteClick} messages={messages} locale={locale} /> <RunsTable projectId={projectId} runs={runs} onDeleteRun={onDeleteClick} messages={messages} locale={locale} />
<DeleteConfirmDialog
isOpen={isDeleteConfirmDialogOpen}
onCancel={closeDeleteConfirmDialog}
onConfirm={onConfirm}
closeText={messages.close}
confirmText={messages.areYouSure}
deleteText={messages.delete}
/>
</div> </div>
); );
} }

View File

@@ -13,6 +13,9 @@ export default function Page({ params }: { params: { projectId: string; locale:
newRun: t('new_run'), newRun: t('new_run'),
deleteRun: t('delete_run'), deleteRun: t('delete_run'),
noRunsFound: t('no_runs_found'), noRunsFound: t('no_runs_found'),
close: t('close'),
areYouSure: t('are_you_sure'),
delete: t('delete'),
}; };
return ( return (

View File

@@ -41,6 +41,9 @@ type RunsMessages = {
newRun: string; newRun: string;
deleteRun: string; deleteRun: string;
noRunsFound: string; noRunsFound: string;
close: string;
areYouSure: string;
delete: string;
}; };
type RunMessages = { type RunMessages = {