Display searched project from different organization (#52)
* Refactor to remove use of organization project * Remove organization project from member tab panel * Handle review changes --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
8bbe2583cb
commit
8ead083ab3
@ -1,28 +1,20 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React from 'react';
|
||||||
import { Project } from 'gql-client';
|
import { Project } from 'gql-client';
|
||||||
|
|
||||||
import { Typography, Button, Chip } from '@material-tailwind/react';
|
import { Typography, Button, Chip } from '@material-tailwind/react';
|
||||||
|
|
||||||
import ActivityCard from './ActivityCard';
|
import ActivityCard from './ActivityCard';
|
||||||
import activityDetails from '../../../assets/activities.json';
|
import activityDetails from '../../../assets/activities.json';
|
||||||
import { ProjectDetails } from '../../../types/project';
|
|
||||||
import { relativeTimeMs } from '../../../utils/time';
|
import { relativeTimeMs } from '../../../utils/time';
|
||||||
|
|
||||||
interface OverviewProps {
|
interface OverviewProps {
|
||||||
project: Project;
|
project: Project;
|
||||||
organizationProject: ProjectDetails;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const OverviewTabPanel = ({ project, organizationProject }: OverviewProps) => {
|
// TODO: Check any live domain is set for production branch
|
||||||
// TODO: Fetch current deployment
|
const IS_DOMAIN_SETUP = true;
|
||||||
const currentDeploymentTitle = useMemo(() => {
|
|
||||||
const deployment = organizationProject?.deployments.find((deployment) => {
|
|
||||||
return deployment.isCurrent === true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return deployment?.title;
|
|
||||||
}, [organizationProject]);
|
|
||||||
|
|
||||||
|
const OverviewTabPanel = ({ project }: OverviewProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-5">
|
<div className="grid grid-cols-5">
|
||||||
<div className="col-span-3 p-2">
|
<div className="col-span-3 p-2">
|
||||||
@ -39,17 +31,24 @@ const OverviewTabPanel = ({ project, organizationProject }: OverviewProps) => {
|
|||||||
<div className="flex justify-between p-2 text-sm items-center">
|
<div className="flex justify-between p-2 text-sm items-center">
|
||||||
<div>
|
<div>
|
||||||
^ Domain
|
^ Domain
|
||||||
{!organizationProject.domain && (
|
{!IS_DOMAIN_SETUP && (
|
||||||
<Chip
|
<Chip
|
||||||
className="normal-case ml-6 bg-[#FED7AA] text-[#EA580C] inline font-normal"
|
className="normal-case ml-6 inline font-normal"
|
||||||
size="sm"
|
size="sm"
|
||||||
value="Not connected"
|
value="Not connected"
|
||||||
icon="^"
|
icon="^"
|
||||||
|
color="orange"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{organizationProject.domain ? (
|
{IS_DOMAIN_SETUP ? (
|
||||||
<p>{organizationProject.domain}</p>
|
<Chip
|
||||||
|
className="normal-case ml-6 inline font-normal"
|
||||||
|
size="sm"
|
||||||
|
value="Connected"
|
||||||
|
icon="^"
|
||||||
|
color="green"
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Button className="normal-case rounded-full" color="blue" size="sm">
|
<Button className="normal-case rounded-full" color="blue" size="sm">
|
||||||
Setup
|
Setup
|
||||||
@ -58,11 +57,13 @@ const OverviewTabPanel = ({ project, organizationProject }: OverviewProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between p-2 text-sm">
|
<div className="flex justify-between p-2 text-sm">
|
||||||
<p>^ Source</p>
|
<p>^ Source</p>
|
||||||
<p>{organizationProject.source}</p>
|
<p>{project.deployments[0]?.branch}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between p-2 text-sm">
|
<div className="flex justify-between p-2 text-sm">
|
||||||
<p>^ Deployment</p>
|
<p>^ Deployment</p>
|
||||||
<p className="text-blue-600">{currentDeploymentTitle}</p>
|
<p className="text-blue-600">
|
||||||
|
{project.deployments[0]?.domain?.name}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between p-2 text-sm">
|
<div className="flex justify-between p-2 text-sm">
|
||||||
<p>^ Created</p>
|
<p>^ Created</p>
|
||||||
|
@ -4,12 +4,10 @@ import { Project } from 'gql-client';
|
|||||||
|
|
||||||
import OverviewTabPanel from './OverviewTabPanel';
|
import OverviewTabPanel from './OverviewTabPanel';
|
||||||
import DeploymentsTabPanel from './DeploymentsTabPanel';
|
import DeploymentsTabPanel from './DeploymentsTabPanel';
|
||||||
import { ProjectDetails } from '../../../types/project';
|
|
||||||
import SettingsTabPanel from './SettingsTabPanel';
|
import SettingsTabPanel from './SettingsTabPanel';
|
||||||
|
|
||||||
interface ProjectTabsProps {
|
interface ProjectTabsProps {
|
||||||
project: Project;
|
project: Project;
|
||||||
organizationProject: ProjectDetails;
|
|
||||||
onUpdate: () => Promise<void>;
|
onUpdate: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,11 +29,7 @@ const Integrations = () => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ProjectTabs = ({
|
const ProjectTabs = ({ project, onUpdate }: ProjectTabsProps) => {
|
||||||
project,
|
|
||||||
onUpdate,
|
|
||||||
organizationProject,
|
|
||||||
}: ProjectTabsProps) => {
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
selectedTabClassName={
|
selectedTabClassName={
|
||||||
@ -50,10 +44,7 @@ const ProjectTabs = ({
|
|||||||
<Tab className={'p-2 cursor-pointer'}>Settings</Tab>
|
<Tab className={'p-2 cursor-pointer'}>Settings</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<OverviewTabPanel
|
<OverviewTabPanel project={project} />
|
||||||
project={project}
|
|
||||||
organizationProject={organizationProject}
|
|
||||||
/>
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<DeploymentsTabPanel projectId={project.id} />
|
<DeploymentsTabPanel projectId={project.id} />
|
||||||
|
@ -1,33 +1,21 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useOutletContext, useParams } from 'react-router-dom';
|
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
import { Project } from 'gql-client';
|
import { Project } from 'gql-client';
|
||||||
|
|
||||||
import { Chip, Button, Typography } from '@material-tailwind/react';
|
import { Chip, Button, Typography } from '@material-tailwind/react';
|
||||||
|
|
||||||
import MemberCard from './MemberCard';
|
import MemberCard from './MemberCard';
|
||||||
|
import { ProjectMember } from '../../../../types/project';
|
||||||
import {
|
|
||||||
ProjectMember,
|
|
||||||
ProjectSearchOutletContext,
|
|
||||||
} from '../../../../types/project';
|
|
||||||
import AddMemberDialog from './AddMemberDialog';
|
import AddMemberDialog from './AddMemberDialog';
|
||||||
import { useGQLClient } from '../../../../context/GQLClientContext';
|
import { useGQLClient } from '../../../../context/GQLClientContext';
|
||||||
|
|
||||||
const FIRST_MEMBER_CARD = 0;
|
const FIRST_MEMBER_CARD = 0;
|
||||||
|
|
||||||
const MembersTabPanel = ({ project }: { project: Project }) => {
|
const MembersTabPanel = ({ project }: { project: Project }) => {
|
||||||
const { id } = useParams();
|
|
||||||
const client = useGQLClient();
|
const client = useGQLClient();
|
||||||
|
|
||||||
const [addmemberDialogOpen, setAddMemberDialogOpen] = useState(false);
|
const [addmemberDialogOpen, setAddMemberDialogOpen] = useState(false);
|
||||||
|
|
||||||
const { projects } = useOutletContext<ProjectSearchOutletContext>();
|
|
||||||
|
|
||||||
const currentProject = useMemo(() => {
|
|
||||||
return projects.find((project) => project.id === id);
|
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
const [projectMembers, setProjectMembers] = useState<ProjectMember[]>([]);
|
const [projectMembers, setProjectMembers] = useState<ProjectMember[]>([]);
|
||||||
|
|
||||||
const addMemberHandler = useCallback((projectMember: ProjectMember) => {
|
const addMemberHandler = useCallback((projectMember: ProjectMember) => {
|
||||||
@ -36,14 +24,10 @@ const MembersTabPanel = ({ project }: { project: Project }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchProjectMembers = useCallback(async () => {
|
const fetchProjectMembers = useCallback(async () => {
|
||||||
if (currentProject) {
|
const { projectMembers } = await client.getProjectMembers(project.id);
|
||||||
const { projectMembers } = await client.getProjectMembers(
|
|
||||||
currentProject.id,
|
|
||||||
);
|
|
||||||
|
|
||||||
setProjectMembers(projectMembers);
|
setProjectMembers(projectMembers);
|
||||||
}
|
}, [project.id]);
|
||||||
}, [currentProject]);
|
|
||||||
|
|
||||||
const removeMemberHandler = async (projectMemberId: string) => {
|
const removeMemberHandler = async (projectMemberId: string) => {
|
||||||
const { removeMember: isMemberRemoved } =
|
const { removeMember: isMemberRemoved } =
|
||||||
@ -59,7 +43,7 @@ const MembersTabPanel = ({ project }: { project: Project }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchProjectMembers();
|
fetchProjectMembers();
|
||||||
}, []);
|
}, [project.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-2 mb-20">
|
<div className="p-2 mb-20">
|
||||||
@ -98,7 +82,7 @@ const MembersTabPanel = ({ project }: { project: Project }) => {
|
|||||||
member={projectMember.member}
|
member={projectMember.member}
|
||||||
key={projectMember.id}
|
key={projectMember.id}
|
||||||
isFirstCard={index === FIRST_MEMBER_CARD}
|
isFirstCard={index === FIRST_MEMBER_CARD}
|
||||||
isOwner={projectMember.member.id === currentProject?.owner.id}
|
isOwner={projectMember.member.id === project.owner.id}
|
||||||
isPending={projectMember.member.name === ''}
|
isPending={projectMember.member.name === ''}
|
||||||
permissions={projectMember.permissions}
|
permissions={projectMember.permissions}
|
||||||
handleDeletePendingMember={(id: string) => {
|
handleDeletePendingMember={(id: string) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useNavigate, useOutletContext, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Project as ProjectType } from 'gql-client';
|
import { Project as ProjectType } from 'gql-client';
|
||||||
|
|
||||||
import { Button, Typography } from '@material-tailwind/react';
|
import { Button, Typography } from '@material-tailwind/react';
|
||||||
@ -7,7 +7,6 @@ import { Button, Typography } from '@material-tailwind/react';
|
|||||||
import HorizontalLine from '../../components/HorizontalLine';
|
import HorizontalLine from '../../components/HorizontalLine';
|
||||||
import ProjectTabs from '../../components/projects/project/ProjectTabs';
|
import ProjectTabs from '../../components/projects/project/ProjectTabs';
|
||||||
import { useGQLClient } from '../../context/GQLClientContext';
|
import { useGQLClient } from '../../context/GQLClientContext';
|
||||||
import { ProjectSearchOutletContext } from '../../types/project';
|
|
||||||
|
|
||||||
const Project = () => {
|
const Project = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@ -31,19 +30,9 @@ const Project = () => {
|
|||||||
await fetchProject(id);
|
await fetchProject(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Remove organization projects
|
|
||||||
const { projects: organizationProjects } =
|
|
||||||
useOutletContext<ProjectSearchOutletContext>();
|
|
||||||
|
|
||||||
const organizationProject = useMemo(() => {
|
|
||||||
return organizationProjects.find((project) => {
|
|
||||||
return project.id === id;
|
|
||||||
});
|
|
||||||
}, [id, organizationProjects]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
{project && organizationProject ? (
|
{project ? (
|
||||||
<>
|
<>
|
||||||
<div className="flex p-4 gap-4 items-center">
|
<div className="flex p-4 gap-4 items-center">
|
||||||
<Button
|
<Button
|
||||||
@ -65,11 +54,7 @@ const Project = () => {
|
|||||||
</div>
|
</div>
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<ProjectTabs
|
<ProjectTabs project={project} onUpdate={onUpdate} />
|
||||||
project={project}
|
|
||||||
organizationProject={organizationProject}
|
|
||||||
onUpdate={onUpdate}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link, useOutletContext } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Button, Typography, Chip } from '@material-tailwind/react';
|
|
||||||
|
|
||||||
import ProjectCard from '../../components/projects/ProjectCard';
|
|
||||||
import { ProjectSearchOutletContext } from '../../types/project';
|
|
||||||
|
|
||||||
const Projects = () => {
|
|
||||||
const { projects } = useOutletContext<ProjectSearchOutletContext>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="flex p-5">
|
|
||||||
<div className="grow">
|
|
||||||
<div className="flex gap-2 items-center">
|
|
||||||
<Typography variant="h4">Projects</Typography>
|
|
||||||
<Chip
|
|
||||||
className="bg-gray-300 rounded-full static"
|
|
||||||
value={projects.length}
|
|
||||||
size="sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Link to="/projects/create">
|
|
||||||
<Button className="rounded-full" color="blue">
|
|
||||||
Create project
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-3 gap-5 p-5">
|
|
||||||
{projects.length !== 0 &&
|
|
||||||
projects.map((project: any, key: number) => {
|
|
||||||
return <ProjectCard project={project} key={key} />;
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Projects;
|
|
@ -1,10 +1,6 @@
|
|||||||
import { Project, Deployment } from 'gql-client';
|
import { Project, Deployment } from 'gql-client';
|
||||||
|
|
||||||
export interface ProjectDetails extends Project {
|
export interface ProjectDetails extends Project {
|
||||||
// TODO: isDomain flag
|
|
||||||
domain?: string | null;
|
|
||||||
// TODO: Use deployment branch
|
|
||||||
source?: string;
|
|
||||||
latestCommit: Commit;
|
latestCommit: Commit;
|
||||||
|
|
||||||
// TODO: Move out of project
|
// TODO: Move out of project
|
||||||
|
Loading…
Reference in New Issue
Block a user