Create run dialog

This commit is contained in:
Takeshi Kimata
2024-05-26 22:02:14 +09:00
parent 1bab870239
commit 5ae4417c23
8 changed files with 219 additions and 40 deletions

View File

@@ -25,13 +25,13 @@ type Props = {
export default function ProjectDialog({ isOpen, editingProject, onCancel, onSubmit, messages }: Props) {
const [projectName, setProjectName] = useState({
text: editingProject ? editingProject.name : '',
isValid: false,
isInvalid: false,
errorMessage: '',
});
const [projectDetail, setProjectDetail] = useState({
text: editingProject ? editingProject.detail : '',
isValid: false,
isInvalid: false,
errorMessage: '',
});
@@ -67,12 +67,12 @@ export default function ProjectDialog({ isOpen, editingProject, onCancel, onSubm
const clear = () => {
setProjectName({
isValid: false,
isInvalid: false,
text: '',
errorMessage: '',
});
setProjectDetail({
isValid: false,
isInvalid: false,
text: '',
errorMessage: '',
});
@@ -82,7 +82,7 @@ export default function ProjectDialog({ isOpen, editingProject, onCancel, onSubm
if (!projectName.text) {
setProjectName({
text: '',
isValid: false,
isInvalid: true,
errorMessage: messages.pleaseEnter,
});
@@ -107,7 +107,7 @@ export default function ProjectDialog({ isOpen, editingProject, onCancel, onSubm
type="text"
label={messages.projectName}
value={projectName.text}
isInvalid={projectName.isValid}
isInvalid={projectName.isInvalid}
errorMessage={projectName.errorMessage}
onChange={(e) => {
setProjectName({
@@ -119,7 +119,7 @@ export default function ProjectDialog({ isOpen, editingProject, onCancel, onSubm
<Textarea
label={messages.projectDetail}
value={projectDetail.text}
isInvalid={projectDetail.isValid}
isInvalid={projectDetail.isInvalid}
errorMessage={projectDetail.errorMessage}
onChange={(e) => {
setProjectDetail({

View File

@@ -0,0 +1,127 @@
'use client';
import React from 'react';
import { useState, useEffect } from 'react';
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@nextui-org/react';
import { RunType, RunsMessages } from '@/types/run';
type Props = {
isOpen: boolean;
editingRun: RunType | null;
onCancel: () => void;
onSubmit: (name: string, description: string) => void;
messages: RunsMessages;
};
export default function RunDialog({ isOpen, editingRun, onCancel, onSubmit, messages }: Props) {
const [runName, setRunName] = useState({
text: editingRun ? editingRun.name : '',
isInvalid: false,
errorMessage: '',
});
const [runDescription, setRunDescription] = useState({
text: editingRun ? editingRun.description : '',
isInvalid: false,
errorMessage: '',
});
useEffect(() => {
if (editingRun) {
setRunName({
...runName,
text: editingRun.name,
});
setRunDescription({
...runDescription,
text: editingRun.description ? editingRun.description : '',
});
} else {
setRunName({
...runName,
text: '',
});
setRunDescription({
...runDescription,
text: '',
});
}
}, [editingRun]);
const clear = () => {
setRunName({
isInvalid: false,
text: '',
errorMessage: '',
});
setRunDescription({
isInvalid: false,
text: '',
errorMessage: '',
});
};
const validate = () => {
if (!runName.text) {
setRunName({
text: '',
isInvalid: true,
errorMessage: messages.pleaseEnter,
});
return;
}
onSubmit(runName.text, runDescription.text);
clear();
};
return (
<Modal
isOpen={isOpen}
onOpenChange={() => {
onCancel();
}}
>
<ModalContent>
<ModalHeader className="flex flex-col gap-1">{messages.run}</ModalHeader>
<ModalBody>
<Input
type="text"
label={messages.runName}
value={runName.text}
isInvalid={runName.isInvalid}
errorMessage={runName.errorMessage}
onChange={(e) => {
setRunName({
...runName,
text: e.target.value,
});
}}
/>
<Textarea
label={messages.runDescription}
value={runDescription.text}
isInvalid={runDescription.isInvalid}
errorMessage={runDescription.errorMessage}
onChange={(e) => {
setRunDescription({
...runDescription,
text: e.target.value,
});
}}
/>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onCancel}>
{messages.close}
</Button>
<Button color="primary" onPress={validate}>
{editingRun && editingRun.createdAt ? messages.update : messages.create}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}

View File

@@ -3,8 +3,9 @@ import { useEffect, useState } from 'react';
import { Button } from '@nextui-org/react';
import { Plus } from 'lucide-react';
import RunsTable from './RunsTable';
import { fetchRuns, createRun, deleteRun } from './runsControl';
import { RunsMessages } from '@/types/run';
import { fetchRuns, createRun, updateRun, deleteRun } from './runsControl';
import { RunType, RunsMessages } from '@/types/run';
import RunDialog from './RunDialog';
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
type Props = {
@@ -13,9 +14,33 @@ type Props = {
messages: RunsMessages;
};
const defaultRun = {
id: null,
name: 'Untitled Run',
configurations: null,
description: null,
state: null,
projectId: null,
createdAt: null,
updatedAt: null,
};
export default function RunsPage({ projectId, locale, messages }: Props) {
const [runs, setRuns] = useState([]);
// run dialog
const [isRunDialogOpen, setIsRunDialogOpen] = useState(false);
const [editingRun, setEditingRun] = useState<RunType | null>(null);
const openDialogForCreate = () => {
setIsRunDialogOpen(true);
setEditingRun(defaultRun);
};
const closeDialog = () => {
setIsRunDialogOpen(false);
setEditingRun(null);
};
// delete confirm dialog
const [isDeleteConfirmDialogOpen, setIsDeleteConfirmDialogOpen] = useState(false);
const [deleteRunId, setDeleteRunId] = useState<number | null>(null);
@@ -37,27 +62,18 @@ export default function RunsPage({ projectId, locale, messages }: Props) {
fetchDataEffect();
}, []);
const onCreateClick = async () => {
try {
const newRun = await createRun(projectId);
const updateRuns = [...runs];
updateRuns.push(newRun);
setRuns(updateRuns);
} catch (error: any) {
console.error('Error deleting run:', error);
const onSubmit = async (name: string, description: string) => {
if (editingRun && editingRun.createdAt) {
const updatedRun = await updateRun(editingRun);
const updatedRuns = runs.map((run) => (run.id === updatedRun.id ? updatedRun : run));
setRuns(updatedRuns);
} else {
const newRun = await createRun(projectId, name, description);
setRuns([...runs, newRun]);
}
closeDialog();
};
// const onDeleteClick = async (runId: number) => {
// try {
// await deleteRun(runId);
// const data = await fetchRuns(projectId);
// setRuns(data);
// } catch (error: any) {
// console.error('Error deleting run:', error);
// }
// };
const onDeleteClick = (runId: number) => {
setDeleteRunId(runId);
setIsDeleteConfirmDialogOpen(true);
@@ -76,7 +92,7 @@ export default function RunsPage({ projectId, locale, messages }: Props) {
<div className="w-full p-3 flex items-center justify-between">
<h3 className="font-bold">{messages.runList}</h3>
<div>
<Button startContent={<Plus size={16} />} size="sm" color="primary" onClick={onCreateClick}>
<Button startContent={<Plus size={16} />} size="sm" color="primary" onClick={openDialogForCreate}>
{messages.newRun}
</Button>
</div>
@@ -84,6 +100,14 @@ export default function RunsPage({ projectId, locale, messages }: Props) {
<RunsTable projectId={projectId} runs={runs} onDeleteRun={onDeleteClick} messages={messages} locale={locale} />
<RunDialog
isOpen={isRunDialogOpen}
editingRun={editingRun}
onCancel={closeDialog}
onSubmit={onSubmit}
messages={messages}
/>
<DeleteConfirmDialog
isOpen={isDeleteConfirmDialogOpen}
onCancel={closeDeleteConfirmDialog}

View File

@@ -5,15 +5,22 @@ export default function Page({ params }: { params: { projectId: string; locale:
const t = useTranslations('Runs');
const messages = {
runList: t('run_list'),
run: t('run'),
editRun: t('edit_run'),
newRun: t('new_run'),
deleteRun: t('delete_run'),
id: t('id'),
name: t('name'),
description: t('description'),
lastUpdate: t('last_update'),
actions: t('actions'),
newRun: t('new_run'),
deleteRun: t('delete_run'),
runName: t('run_name'),
runDescription: t('run_description'),
noRunsFound: t('no_runs_found'),
close: t('close'),
create: t('create'),
update: t('update'),
pleaseEnter: t('please_enter'),
areYouSure: t('are_you_sure'),
delete: t('delete'),
};

View File

@@ -46,11 +46,11 @@ async function fetchRuns(projectId: string) {
}
}
async function createRun(projectId: string) {
async function createRun(projectId: string, name: string, description: string) {
const newTestRun = {
name: 'untitled run',
name,
configurations: 0,
description: '',
description,
state: 0,
projectId: projectId,
};