Skip to content
This repository has been archived by the owner on Oct 27, 2022. It is now read-only.

Commit

Permalink
New project page header (#1207)
Browse files Browse the repository at this point in the history
* Added new layout

* Fixes
  • Loading branch information
sjaanus committed Aug 8, 2022
1 parent 499740e commit ab5df41
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -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 (
<Dialogue
open={open}
onClick={onClick}
onClose={onClose}
title="Really delete project"
/>
);
};
2 changes: 1 addition & 1 deletion src/component/project/Project/Project.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const useStyles = makeStyles()(theme => ({
marginBottom: '1rem',
},
innerContainer: {
padding: '1rem 2rem',
padding: '1.25rem 2rem',
display: 'flex',
alignItems: 'center',
},
Expand Down
110 changes: 92 additions & 18 deletions src/component/project/Project/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -33,6 +56,8 @@ const Project = () => {
const basePath = `/projects/${projectId}`;
const projectName = project?.name || projectId;

const [showDelDialog, setShowDelDialog] = useState(false);

const tabs = [
{
title: 'Overview',
Expand Down Expand Up @@ -85,21 +110,60 @@ const Project = () => {
<div className={styles.header}>
<div className={styles.innerContainer}>
<h2 className={styles.title}>
<div className={styles.titleText} data-loading>
{projectName}
<div>
<StyledName data-loading>{projectName}</StyledName>
<ConditionallyRender
condition={Boolean(project.description)}
show={
<StyledDiv>
<StyledTitle data-loading>
Description:&nbsp;
</StyledTitle>
<StyledText data-loading>
{project.description}
</StyledText>
</StyledDiv>
}
/>
<StyledDiv>
<StyledTitle data-loading>
projectId:&nbsp;
</StyledTitle>
<StyledText data-loading>
{projectId}
</StyledText>
</StyledDiv>
</div>
<PermissionIconButton
permission={UPDATE_PROJECT}
projectId={projectId}
sx={{ visibility: isOss() ? 'hidden' : 'visible' }}
onClick={() =>
navigate(`/projects/${projectId}/edit`)
}
tooltipProps={{ title: 'Edit project' }}
data-loading
>
<Edit />
</PermissionIconButton>
<StyledDiv>
<PermissionIconButton
permission={UPDATE_PROJECT}
projectId={projectId}
sx={{
visibility: isOss() ? 'hidden' : 'visible',
}}
onClick={() =>
navigate(`/projects/${projectId}/edit`)
}
tooltipProps={{ title: 'Edit project' }}
data-loading
>
<Edit />
</PermissionIconButton>
<PermissionIconButton
permission={DELETE_PROJECT}
projectId={projectId}
sx={{
visibility: isOss() ? 'hidden' : 'visible',
}}
onClick={() => {
setShowDelDialog(true);
}}
tooltipProps={{ title: 'Delete project' }}
data-loading
>
<Delete />
</PermissionIconButton>
</StyledDiv>
</h2>
</div>
<ConditionallyRender
Expand Down Expand Up @@ -132,6 +196,16 @@ const Project = () => {
</Tabs>
</div>
</div>
<DeleteProjectDialogue
project={projectId}
open={showDelDialog}
onClose={() => {
setShowDelDialog(false);
}}
onSuccess={() => {
navigate('/projects');
}}
/>
<Routes>
<Route path="health" element={<ProjectHealth />} />
<Route path="access/*" element={<ProjectAccess />} />
Expand Down
1 change: 1 addition & 0 deletions src/component/project/ProjectCard/ProjectCard.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const useStyles = makeStyles()(theme => ({
boxOrient: 'vertical',
textOverflow: 'ellipsis',
overflow: 'hidden',
alignItems: 'flex-start',
},

projectIcon: {
Expand Down
35 changes: 4 additions & 31 deletions src/component/project/ProjectCard/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -152,15 +127,13 @@ export const ProjectCard = ({
<p data-loading>members</p>
</div>
</div>
<Dialogue
<DeleteProjectDialogue
project={id}
open={showDelDialog}
onClick={onRemoveProject}
onClose={event => {
event.preventDefault();
onClose={() => {
setAnchorEl(null);
setShowDelDialog(false);
}}
title="Really delete project"
/>
</Card>
);
Expand Down

0 comments on commit ab5df41

Please sign in to comment.