175 lines
5.8 KiB
TypeScript
175 lines
5.8 KiB
TypeScript
'use client';
|
|
import { useState, useEffect, useContext } from 'react';
|
|
import { Button, Table, TableHeader, TableColumn, TableBody, TableRow, TableCell } from '@heroui/react';
|
|
import { Pencil, Trash } from 'lucide-react';
|
|
import ProjectTagsManager from './ProjectTagsManager';
|
|
import { SettingsMessages } from '@/types/settings';
|
|
import { TokenContext } from '@/utils/TokenProvider';
|
|
import { deleteProject, fetchProject, updateProject } from '@/utils/projectsControl';
|
|
import { ProjectDialogMessages, ProjectType } from '@/types/project';
|
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
|
import { useRouter } from '@/src/i18n/routing';
|
|
import ProjectDialog from '@/components/ProjectDialog';
|
|
import { UserType } from '@/types/user';
|
|
import { findUser } from '@/utils/usersControl';
|
|
import { logError } from '@/utils/errorHandler';
|
|
import UserAvatar from '@/components/UserAvatar';
|
|
|
|
type Props = {
|
|
projectId: string;
|
|
messages: SettingsMessages;
|
|
projectDialogMessages: ProjectDialogMessages;
|
|
locale: string;
|
|
};
|
|
|
|
export default function SettingsPage({ projectId, messages, projectDialogMessages, locale }: Props) {
|
|
const context = useContext(TokenContext);
|
|
const router = useRouter();
|
|
const [project, setProject] = useState<ProjectType>({
|
|
id: 0,
|
|
name: '',
|
|
detail: '',
|
|
isPublic: false,
|
|
userId: 0,
|
|
createdAt: '',
|
|
updatedAt: '',
|
|
Folders: [],
|
|
Runs: [],
|
|
});
|
|
const [owner, setOwner] = useState<UserType>({
|
|
id: 0,
|
|
email: '',
|
|
password: '',
|
|
avatarPath: '',
|
|
role: -1,
|
|
username: '',
|
|
locale: null,
|
|
});
|
|
|
|
useEffect(() => {
|
|
async function fetchDataEffect() {
|
|
if (!context.isSignedIn()) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const data = await fetchProject(context.token.access_token, Number(projectId));
|
|
setProject(data);
|
|
|
|
if (data.userId) {
|
|
const ownerData = await findUser(context.token.access_token, data.userId);
|
|
setOwner(ownerData);
|
|
} else {
|
|
console.error('failed to get project owner id');
|
|
}
|
|
} catch (error: unknown) {
|
|
logError('Error fetching project data:', error);
|
|
}
|
|
}
|
|
|
|
fetchDataEffect();
|
|
}, [context, projectId]);
|
|
|
|
// project dialog
|
|
const [isProjectDialogOpen, setIsProjectDialogOpen] = useState(false);
|
|
const onSubmit = async (name: string, detail: string, isPublic: boolean) => {
|
|
const updatedProject = await updateProject(context.token.access_token, project.id, name, detail, isPublic);
|
|
setProject(updatedProject);
|
|
setIsProjectDialogOpen(false);
|
|
};
|
|
|
|
// delete confirm dialog
|
|
const [isDeleteConfirmDialogOpen, setIsDeleteConfirmDialogOpen] = useState(false);
|
|
const onConfirm = async () => {
|
|
await deleteProject(context.token.access_token, Number(projectId));
|
|
setIsDeleteConfirmDialogOpen(false);
|
|
router.push(`/projects/`, { locale: locale });
|
|
};
|
|
|
|
return (
|
|
<div className="container mx-auto max-w-3xl pt-6 px-6 flex-grow">
|
|
<div className="w-full p-3 flex items-center justify-between">
|
|
<h3 className="font-bold">{messages.projectManagement}</h3>
|
|
<div>
|
|
<Button
|
|
startContent={<Trash size={16} />}
|
|
size="sm"
|
|
color="danger"
|
|
isDisabled={!context.isProjectOwner(Number(projectId))}
|
|
onPress={() => setIsDeleteConfirmDialogOpen(true)}
|
|
>
|
|
{messages.deleteProject}
|
|
</Button>
|
|
<Button
|
|
startContent={<Pencil size={16} />}
|
|
size="sm"
|
|
color="primary"
|
|
isDisabled={!context.isProjectOwner(Number(projectId))}
|
|
onPress={() => setIsProjectDialogOpen(true)}
|
|
className="ms-2"
|
|
>
|
|
{messages.editProject}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="w-full p-3">
|
|
<Table hideHeader aria-label="Example static collection table">
|
|
<TableHeader>
|
|
<TableColumn>dummy</TableColumn>
|
|
<TableColumn>dummy</TableColumn>
|
|
</TableHeader>
|
|
<TableBody>
|
|
<TableRow key="project-name">
|
|
<TableCell>{messages.projectName}</TableCell>
|
|
<TableCell>{project.name}</TableCell>
|
|
</TableRow>
|
|
<TableRow key="project-detail">
|
|
<TableCell>{messages.projectDetail}</TableCell>
|
|
<TableCell>{project.detail}</TableCell>
|
|
</TableRow>
|
|
<TableRow key="project-owner">
|
|
<TableCell>{messages.projectOwner}</TableCell>
|
|
<TableCell>
|
|
<div className="flex gap-2 items-center">
|
|
<UserAvatar size={24} username={owner.username} avatarPath={owner.avatarPath} />
|
|
<p className="">{owner.username}</p>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow key="project-publicity">
|
|
<TableCell>{messages.publicity}</TableCell>
|
|
<TableCell>{project.isPublic ? messages.public : messages.private}</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
|
|
<div className="w-full p-3 flex items-center justify-between">
|
|
<h3 className="font-bold">{messages.tagManagement}</h3>
|
|
</div>
|
|
|
|
<div className="w-full p-3">
|
|
<ProjectTagsManager projectId={projectId} messages={messages} />
|
|
</div>
|
|
|
|
<ProjectDialog
|
|
isOpen={isProjectDialogOpen}
|
|
editingProject={project}
|
|
onCancel={() => setIsProjectDialogOpen(false)}
|
|
onSubmit={onSubmit}
|
|
projectDialogMessages={projectDialogMessages}
|
|
/>
|
|
|
|
<DeleteConfirmDialog
|
|
isOpen={isDeleteConfirmDialogOpen}
|
|
onCancel={() => setIsDeleteConfirmDialogOpen(false)}
|
|
onConfirm={onConfirm}
|
|
closeText={messages.close}
|
|
confirmText={messages.areYouSure}
|
|
deleteText={messages.delete}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|