fix: projects should not be edited or deleted on the project list page
This commit is contained in:
@@ -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",
|
||||||
|
|||||||
@@ -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": "ホーム",
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
Reference in New Issue
Block a user