diff --git a/frontend/src/component/project/Project/DeleteProject/DeleteProjectDialogue.tsx b/frontend/src/component/project/Project/DeleteProject/DeleteProjectDialogue.tsx new file mode 100644 index 0000000000..aab3c2977b --- /dev/null +++ b/frontend/src/component/project/Project/DeleteProject/DeleteProjectDialogue.tsx @@ -0,0 +1,50 @@ +import { Dialogue } from 'component/common/Dialogue/Dialogue'; +import React from 'react'; +import { formatUnknownError } from 'utils/formatUnknownError'; +import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi'; +import useProjects from 'hooks/api/getters/useProjects/useProjects'; +import useToast from 'hooks/useToast'; + +interface IDeleteProjectDialogueProps { + project: string; + open: boolean; + onClose?: () => void; + onSuccess?: () => void; +} + +export const DeleteProjectDialogue = ({ + open, + onClose, + project, + onSuccess, +}: IDeleteProjectDialogueProps) => { + const { deleteProject } = useProjectApi(); + const { refetch: refetchProjectOverview } = useProjects(); + const { setToastData, setToastApiError } = useToast(); + + const onClick = async (e: React.SyntheticEvent) => { + e.preventDefault(); + try { + await deleteProject(project); + refetchProjectOverview(); + setToastData({ + title: 'Deleted project', + type: 'success', + text: 'Successfully deleted project', + }); + onSuccess?.(); + } catch (ex: unknown) { + setToastApiError(formatUnknownError(ex)); + } + onClose?.(); + }; + + return ( + + ); +}; diff --git a/frontend/src/component/project/Project/Project.styles.ts b/frontend/src/component/project/Project/Project.styles.ts index f2c1e99e6d..76c69128aa 100644 --- a/frontend/src/component/project/Project/Project.styles.ts +++ b/frontend/src/component/project/Project/Project.styles.ts @@ -18,7 +18,7 @@ export const useStyles = makeStyles()(theme => ({ marginBottom: '1rem', }, innerContainer: { - padding: '1rem 2rem', + padding: '1.25rem 2rem', display: 'flex', alignItems: 'center', }, diff --git a/frontend/src/component/project/Project/Project.tsx b/frontend/src/component/project/Project/Project.tsx index 0d31656cd1..14fb794a55 100644 --- a/frontend/src/component/project/Project/Project.tsx +++ b/frontend/src/component/project/Project/Project.tsx @@ -4,21 +4,44 @@ import useLoading from 'hooks/useLoading'; import ApiError from 'component/common/ApiError/ApiError'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { useStyles } from './Project.styles'; -import { Tab, Tabs } from '@mui/material'; -import { Edit } from '@mui/icons-material'; +import { styled, Tab, Tabs } from '@mui/material'; +import { Delete, Edit } from '@mui/icons-material'; import useToast from 'hooks/useToast'; import useQueryParams from 'hooks/useQueryParams'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { ProjectAccess } from '../ProjectAccess/ProjectAccess'; import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment'; import { ProjectFeaturesArchive } from './ProjectFeaturesArchive/ProjectFeaturesArchive'; import ProjectOverview from './ProjectOverview'; import ProjectHealth from './ProjectHealth/ProjectHealth'; import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; -import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions'; +import { + DELETE_PROJECT, + UPDATE_PROJECT, +} from 'component/providers/AccessProvider/permissions'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { Routes, Route, useLocation } from 'react-router-dom'; +import { DeleteProjectDialogue } from './DeleteProject/DeleteProjectDialogue'; + +const StyledDiv = styled('div')(() => ({ + display: 'flex', +})); + +const StyledName = styled('div')(({ theme }) => ({ + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + paddingBottom: theme.spacing(2), +})); + +const StyledTitle = styled('span')(({ theme }) => ({ + fontSize: theme.fontSizes.smallBody, + fontWeight: 'normal', +})); +const StyledText = styled(StyledTitle)(({ theme }) => ({ + color: theme.palette.grey[800], +})); const Project = () => { const projectId = useRequiredPathParam('projectId'); @@ -33,6 +56,8 @@ const Project = () => { const basePath = `/projects/${projectId}`; const projectName = project?.name || projectId; + const [showDelDialog, setShowDelDialog] = useState(false); + const tabs = [ { title: 'Overview', @@ -85,21 +110,60 @@ const Project = () => {

-
- {projectName} +
+ {projectName} + + + Description:  + + + {project.description} + + + } + /> + + + projectId:  + + + {projectId} + +
- - navigate(`/projects/${projectId}/edit`) - } - tooltipProps={{ title: 'Edit project' }} - data-loading - > - - + + + navigate(`/projects/${projectId}/edit`) + } + tooltipProps={{ title: 'Edit project' }} + data-loading + > + + + { + setShowDelDialog(true); + }} + tooltipProps={{ title: 'Delete project' }} + data-loading + > + + +

{
+ { + setShowDelDialog(false); + }} + onSuccess={() => { + navigate('/projects'); + }} + /> } /> } /> diff --git a/frontend/src/component/project/ProjectCard/ProjectCard.styles.ts b/frontend/src/component/project/ProjectCard/ProjectCard.styles.ts index 1f20c987bf..849697ecbe 100644 --- a/frontend/src/component/project/ProjectCard/ProjectCard.styles.ts +++ b/frontend/src/component/project/ProjectCard/ProjectCard.styles.ts @@ -32,6 +32,7 @@ export const useStyles = makeStyles()(theme => ({ boxOrient: 'vertical', textOverflow: 'ellipsis', overflow: 'hidden', + alignItems: 'flex-start', }, projectIcon: { diff --git a/frontend/src/component/project/ProjectCard/ProjectCard.tsx b/frontend/src/component/project/ProjectCard/ProjectCard.tsx index c6e44a532b..815432ea0f 100644 --- a/frontend/src/component/project/ProjectCard/ProjectCard.tsx +++ b/frontend/src/component/project/ProjectCard/ProjectCard.tsx @@ -4,21 +4,17 @@ import MoreVertIcon from '@mui/icons-material/MoreVert'; import { ReactComponent as ProjectIcon } from 'assets/icons/projectIcon.svg'; import React, { useState, SyntheticEvent, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Dialogue } from 'component/common/Dialogue/Dialogue'; -import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi'; -import useProjects from 'hooks/api/getters/useProjects/useProjects'; import { Delete, Edit } from '@mui/icons-material'; import { getProjectEditPath } from 'utils/routePathHelpers'; import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; -import useToast from 'hooks/useToast'; import { UPDATE_PROJECT, DELETE_PROJECT, } from 'component/providers/AccessProvider/permissions'; -import { formatUnknownError } from 'utils/formatUnknownError'; import AccessContext from 'contexts/AccessContext'; import { DEFAULT_PROJECT_ID } from 'hooks/api/getters/useDefaultProject/useDefaultProjectId'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; +import { DeleteProjectDialogue } from '../Project/DeleteProject/DeleteProjectDialogue'; interface IProjectCardProps { name: string; @@ -40,36 +36,15 @@ export const ProjectCard = ({ const { classes } = useStyles(); const { hasAccess } = useContext(AccessContext); const { isOss } = useUiConfig(); - const { refetch: refetchProjectOverview } = useProjects(); const [anchorEl, setAnchorEl] = useState(null); const [showDelDialog, setShowDelDialog] = useState(false); - const { deleteProject } = useProjectApi(); const navigate = useNavigate(); - const { setToastData, setToastApiError } = useToast(); - // @ts-expect-error const handleClick = e => { e.preventDefault(); setAnchorEl(e.currentTarget); }; - const onRemoveProject = async (e: React.SyntheticEvent) => { - e.preventDefault(); - try { - await deleteProject(id); - refetchProjectOverview(); - setToastData({ - title: 'Deleted project', - type: 'success', - text: 'Successfully deleted project', - }); - } catch (e: unknown) { - setToastApiError(formatUnknownError(e)); - } - setShowDelDialog(false); - setAnchorEl(null); - }; - const canDeleteProject = hasAccess(DELETE_PROJECT, id) && id !== DEFAULT_PROJECT_ID; @@ -152,15 +127,13 @@ export const ProjectCard = ({

members

- { - event.preventDefault(); + onClose={() => { setAnchorEl(null); setShowDelDialog(false); }} - title="Really delete project" /> );