fix: projects should not be edited or deleted on the project list page

This commit is contained in:
Takeshi Kimata
2024-07-18 09:43:29 +09:00
parent 32ddf0f1d8
commit 76b7aa0dac
6 changed files with 11 additions and 116 deletions

View File

@@ -80,14 +80,11 @@
"projectList": "Project List", "projectList": "Project List",
"project": "Project", "project": "Project",
"new_project": "New Project", "new_project": "New Project",
"edit_project": "Edit Project",
"delete_project": "Delete Project",
"id": "ID", "id": "ID",
"publicity": "Publicity", "publicity": "Publicity",
"name": "Name", "name": "Name",
"detail": "Detail", "detail": "Detail",
"last_update": "Last update", "last_update": "Last update",
"actions": "Actions",
"project_name": "Project Name", "project_name": "Project Name",
"project_detail": "Project Detail", "project_detail": "Project Detail",
"public": "Public", "public": "Public",
@@ -95,11 +92,8 @@
"if_you_make_public": "Making a project public makes it visible to users who are not project members.", "if_you_make_public": "Making a project public makes it visible to users who are not project members.",
"close": "Close", "close": "Close",
"create": "Create", "create": "Create",
"update": "Update",
"please_enter": "Please enter project name", "please_enter": "Please enter project name",
"no_projects_found": "No projects found", "no_projects_found": "No projects found"
"are_you_sure": "Are you sure you want to delete the project?",
"delete": "Delete"
}, },
"Project": { "Project": {
"home": "Home", "home": "Home",

View File

@@ -80,14 +80,11 @@
"projectList": "プロジェクト一覧", "projectList": "プロジェクト一覧",
"project": "プロジェクト", "project": "プロジェクト",
"new_project": "新規プロジェクト", "new_project": "新規プロジェクト",
"edit_project": "プロジェクトの編集",
"delete_project": "プロジェクトの削除",
"id": "ID", "id": "ID",
"publicity": "公開", "publicity": "公開",
"name": "名前", "name": "名前",
"detail": "詳細", "detail": "詳細",
"last_update": "最終更新", "last_update": "最終更新",
"actions": "アクション",
"project_name": "プロジェクト名", "project_name": "プロジェクト名",
"project_detail": "プロジェクト詳細", "project_detail": "プロジェクト詳細",
"public": "パブリック", "public": "パブリック",
@@ -95,11 +92,8 @@
"if_you_make_public": "プロジェクトをパブリックにすると、プロジェクトメンバーではないユーザーからも見えるようになります。", "if_you_make_public": "プロジェクトをパブリックにすると、プロジェクトメンバーではないユーザーからも見えるようになります。",
"close": "閉じる", "close": "閉じる",
"create": "作成", "create": "作成",
"update": "更新",
"please_enter": "プロジェクト名を入力してください", "please_enter": "プロジェクト名を入力してください",
"no_projects_found": "プロジェクトがありません", "no_projects_found": "プロジェクトがありません"
"are_you_sure": "プロジェクトを削除してもよろしいですか?",
"delete": "削除"
}, },
"Project": { "Project": {
"home": "ホーム", "home": "ホーム",

View File

@@ -6,8 +6,7 @@ import { TokenContext } from '@/utils/TokenProvider';
import { ProjectType, ProjectsMessages } from '@/types/project'; import { ProjectType, ProjectsMessages } from '@/types/project';
import ProjectsTable from './ProjectsTable'; import ProjectsTable from './ProjectsTable';
import ProjectDialog from '@/components/ProjectDialog'; import ProjectDialog from '@/components/ProjectDialog';
import { fetchProjects, createProject, updateProject, deleteProject } from '@/utils/projectsControl'; import { fetchProjects, createProject } from '@/utils/projectsControl';
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
export type Props = { export type Props = {
messages: ProjectsMessages; messages: ProjectsMessages;
@@ -16,7 +15,7 @@ export type Props = {
export default function ProjectsPage({ messages, locale }: Props) { export default function ProjectsPage({ messages, locale }: Props) {
const context = useContext(TokenContext); const context = useContext(TokenContext);
const [projects, setProjects] = useState([]); const [projects, setProjects] = useState<ProjectType[]>([]);
useEffect(() => { useEffect(() => {
async function fetchDataEffect() { async function fetchDataEffect() {
@@ -47,47 +46,15 @@ export default function ProjectsPage({ messages, locale }: Props) {
setEditingProject(null); setEditingProject(null);
}; };
// delete confirm dialog
const [isDeleteConfirmDialogOpen, setIsDeleteConfirmDialogOpen] = useState(false);
const [deleteProjectId, setDeleteProjectId] = useState<number | null>(null);
const closeDeleteConfirmDialog = () => {
setIsDeleteConfirmDialogOpen(false);
setDeleteProjectId(null);
};
const onSubmit = async (name: string, detail: string, isPublic: boolean) => { const onSubmit = async (name: string, detail: string, isPublic: boolean) => {
if (editingProject) { const newProject = await createProject(context.token.access_token, name, detail, isPublic);
const updatedProject = await updateProject(context.token.access_token, editingProject.id, name, detail, isPublic); setProjects([...projects, newProject]);
const updatedProjects = projects.map((project) => (project.id === updatedProject.id ? updatedProject : project));
setProjects(updatedProjects);
} else {
const newProject = await createProject(context.token.access_token, name, detail, isPublic);
setProjects([...projects, newProject]);
// refresh project roles // refresh project roles
context.refreshProjectRoles(); context.refreshProjectRoles();
}
closeDialog(); closeDialog();
}; };
const onEditClick = (project: ProjectType) => {
setEditingProject(project);
setIsProjectDialogOpen(true);
};
const onDeleteClick = (projectId: number) => {
setDeleteProjectId(projectId);
setIsDeleteConfirmDialogOpen(true);
};
const onConfirm = async () => {
if (deleteProjectId) {
await deleteProject(context.token.access_token, deleteProjectId);
setProjects(projects.filter((project) => project.id !== deleteProjectId));
closeDeleteConfirmDialog();
}
};
return ( return (
<div className="container mx-auto max-w-3xl pt-16 px-6 flex-grow"> <div className="container mx-auto max-w-3xl pt-16 px-6 flex-grow">
<div className="w-full p-3 flex items-center justify-between"> <div className="w-full p-3 flex items-center justify-between">
@@ -99,13 +66,7 @@ export default function ProjectsPage({ messages, locale }: Props) {
</div> </div>
</div> </div>
<ProjectsTable <ProjectsTable projects={projects} messages={messages} locale={locale} />
projects={projects}
onEditProject={onEditClick}
onDeleteProject={onDeleteClick}
messages={messages}
locale={locale}
/>
<ProjectDialog <ProjectDialog
isOpen={isProjectDialogOpen} isOpen={isProjectDialogOpen}
@@ -114,15 +75,6 @@ export default function ProjectsPage({ messages, locale }: Props) {
onSubmit={onSubmit} onSubmit={onSubmit}
messages={messages} messages={messages}
/> />
<DeleteConfirmDialog
isOpen={isDeleteConfirmDialogOpen}
onCancel={closeDeleteConfirmDialog}
onConfirm={onConfirm}
closeText={messages.close}
confirmText={messages.areYouSure}
deleteText={messages.delete}
/>
</div> </div>
); );
} }

View File

@@ -1,39 +1,22 @@
import { useState, useMemo, useCallback } from 'react'; import { useState, useMemo, useCallback } from 'react';
import { import { Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, SortDescriptor } from '@nextui-org/react';
Table,
TableHeader,
TableColumn,
TableBody,
TableRow,
TableCell,
Button,
DropdownTrigger,
Dropdown,
DropdownMenu,
DropdownItem,
SortDescriptor,
} from '@nextui-org/react';
import { Link, NextUiLinkClasses } from '@/src/navigation'; import { Link, NextUiLinkClasses } from '@/src/navigation';
import { MoreVertical } from 'lucide-react';
import { ProjectType, ProjectsMessages } from '@/types/project'; import { ProjectType, ProjectsMessages } from '@/types/project';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import PublicityChip from '@/components/PublicityChip'; import PublicityChip from '@/components/PublicityChip';
type Props = { type Props = {
projects: ProjectType[]; projects: ProjectType[];
onEditProject: (project: ProjectType) => void;
onDeleteProject: (projectId: number) => void;
messages: ProjectsMessages; messages: ProjectsMessages;
locale: string; locale: string;
}; };
export default function ProjectsTable({ projects, onEditProject, onDeleteProject, messages, locale }: Props) { export default function ProjectsTable({ projects, messages, locale }: Props) {
const headerColumns = [ const headerColumns = [
{ name: messages.id, uid: 'id', sortable: true }, { name: messages.id, uid: 'id', sortable: true },
{ name: messages.publicity, uid: 'isPublic', sortable: true }, { name: messages.publicity, uid: 'isPublic', sortable: true },
{ name: messages.name, uid: 'name', sortable: true }, { name: messages.name, uid: 'name', sortable: true },
{ name: messages.lastUpdate, uid: 'updatedAt', sortable: true }, { name: messages.lastUpdate, uid: 'updatedAt', sortable: true },
{ name: messages.actions, uid: 'actions' },
]; ];
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({ const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
@@ -78,22 +61,6 @@ export default function ProjectsTable({ projects, onEditProject, onDeleteProject
); );
case 'updatedAt': case 'updatedAt':
return <span>{dayjs(cellValue).format('YYYY/MM/DD HH:mm')}</span>; return <span>{dayjs(cellValue).format('YYYY/MM/DD HH:mm')}</span>;
case 'actions':
return (
<Dropdown>
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
<MoreVertical size={16} />
</Button>
</DropdownTrigger>
<DropdownMenu aria-label="project actions">
<DropdownItem onClick={() => onEditProject(project)}>{messages.editProject}</DropdownItem>
<DropdownItem className="text-danger" onClick={() => onDeleteProject(project.id)}>
{messages.deleteProject}
</DropdownItem>
</DropdownMenu>
</Dropdown>
);
default: default:
return cellValue; return cellValue;
} }

View File

@@ -7,14 +7,11 @@ export default function Page(params: { locale: string }) {
projectList: t('projectList'), projectList: t('projectList'),
project: t('project'), project: t('project'),
newProject: t('new_project'), newProject: t('new_project'),
editProject: t('edit_project'),
deleteProject: t('delete_project'),
id: t('id'), id: t('id'),
publicity: t('publicity'), publicity: t('publicity'),
name: t('name'), name: t('name'),
detail: t('detail'), detail: t('detail'),
lastUpdate: t('last_update'), lastUpdate: t('last_update'),
actions: t('actions'),
projectName: t('project_name'), projectName: t('project_name'),
projectDetail: t('project_detail'), projectDetail: t('project_detail'),
public: t('public'), public: t('public'),
@@ -22,11 +19,8 @@ export default function Page(params: { locale: string }) {
ifYouMakePublic: t('if_you_make_public'), ifYouMakePublic: t('if_you_make_public'),
close: t('close'), close: t('close'),
create: t('create'), create: t('create'),
update: t('update'),
pleaseEnter: t('please_enter'), pleaseEnter: t('please_enter'),
noProjectsFound: t('no_projects_found'), noProjectsFound: t('no_projects_found'),
areYouSure: t('are_you_sure'),
delete: t('delete'),
}; };
return ( return (
<> <>

View File

@@ -16,14 +16,11 @@ export type ProjectType = {
export type ProjectsMessages = { export type ProjectsMessages = {
projectList: string; projectList: string;
newProject: string; newProject: string;
editProject: string;
deleteProject: string;
id: string; id: string;
publicity: string; publicity: string;
name: string; name: string;
detail: string; detail: string;
lastUpdate: string; lastUpdate: string;
actions: string;
projectName: string; projectName: string;
projectDetail: string; projectDetail: string;
public: string; public: string;
@@ -31,11 +28,8 @@ export type ProjectsMessages = {
ifYouMakePublic: string; ifYouMakePublic: string;
close: string; close: string;
create: string; create: string;
update: string;
pleaseEnter: string; pleaseEnter: string;
noProjectsFound: string; noProjectsFound: string;
areYouSure: string;
delete: string;
}; };
export type ProjectMessages = { export type ProjectMessages = {