diff --git a/packages/frontend/src/assets/deployments.json b/packages/frontend/src/assets/deployments.json index df0c28b0..af876988 100644 --- a/packages/frontend/src/assets/deployments.json +++ b/packages/frontend/src/assets/deployments.json @@ -4,6 +4,7 @@ "title": "nextjs-boilerplate-9t44zbky4dg-bygideon-projects", "status": "Building", "isProduction": true, + "isCurrent": false, "branch": "prod", "commit": { "hash": "9haif19", @@ -17,6 +18,7 @@ "title": "nextjs-boilerplate-9232dwky4dg-bygideon-projects", "status": "Ready", "isProduction": false, + "isCurrent": false, "branch": "prod", "commit": { "hash": "43de569", @@ -30,6 +32,7 @@ "title": "nextjs-boilerplate-9saa22y4dg-bygideon-projects", "status": "Error", "isProduction": false, + "isCurrent": false, "branch": "main", "commit": { "hash": "4hdsf19", diff --git a/packages/frontend/src/components/projects/ProjectSearchBar.tsx b/packages/frontend/src/components/projects/ProjectSearchBar.tsx index b958eaa3..45655d55 100644 --- a/packages/frontend/src/components/projects/ProjectSearchBar.tsx +++ b/packages/frontend/src/components/projects/ProjectSearchBar.tsx @@ -11,13 +11,13 @@ import { import SearchBar from '../SearchBar'; import { ProjectDetails } from '../../types/project'; -import projectsData from '../../assets/projects.json'; interface ProjectsSearchProps { + projects: ProjectDetails[]; onChange?: (data: ProjectDetails) => void; } -const ProjectSearchBar = ({ onChange }: ProjectsSearchProps) => { +const ProjectSearchBar = ({ projects, onChange }: ProjectsSearchProps) => { const [items, setItems] = useState([]); const [selectedItem, setSelectedItem] = useState(null); @@ -32,7 +32,7 @@ const ProjectSearchBar = ({ onChange }: ProjectsSearchProps) => { onInputValueChange({ inputValue }) { setItems( inputValue - ? projectsData.filter((project) => + ? projects.filter((project) => project.title.toLowerCase().includes(inputValue.toLowerCase()), ) : [], diff --git a/packages/frontend/src/components/projects/project/OverviewTabPanel.tsx b/packages/frontend/src/components/projects/project/OverviewTabPanel.tsx index 1d49843d..37208b37 100644 --- a/packages/frontend/src/components/projects/project/OverviewTabPanel.tsx +++ b/packages/frontend/src/components/projects/project/OverviewTabPanel.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { Typography, Button, Chip } from '@material-tailwind/react'; @@ -11,67 +11,79 @@ interface OverviewProps { project: ProjectDetails; } -const OverviewTabPanel = ({ project }: OverviewProps) => ( -
-
-
-
^
-
- {project.name} - - {project.url} - +const OverviewTabPanel = ({ project }: OverviewProps) => { + const currentDeploymentTitle = useMemo(() => { + const deployment = project.deployments.find((deployment) => { + return deployment.isCurrent === true; + }); + + return deployment?.title; + }, []); + + return ( +
+
+
+
^
+
+ {project.name} + + {project.url} + +
-
-
-
- ^ Domain - {!project.domain && ( - +
+
+ ^ Domain + {!project.domain && ( + + )} +
+ {project.domain ? ( +

{project.domain}

+ ) : ( + )}
- {project.domain ? ( -

{project.domain}

- ) : ( - - )} +
+

^ Source

+

{project.source}

+
+
+

^ Deployment

+

{currentDeploymentTitle}

+
+
+

^ Created

+

+ {/* TODO: Use following time conversion wherever required */} + {relativeTime(new Date(Number(project.createdAt)).toISOString())} by + ^ {project.createdBy} +

+
-
-

^ Source

-

{project.source}

-
-
-

^ Deployment

-

{project.deployment}

-
-
-

^ Created

-

- {relativeTime(project.createdAt)} by ^ {project.createdBy} -

+
+
+ Activity + +
+
+ {activityDetails.map((activity, key) => { + return ; + })} +
-
-
- Activity - -
-
- {activityDetails.map((activity, key) => { - return ; - })} -
-
-
-); + ); +}; export default OverviewTabPanel; diff --git a/packages/frontend/src/components/projects/project/settings/Domains.tsx b/packages/frontend/src/components/projects/project/settings/Domains.tsx index 5676edad..b4b6f80e 100644 --- a/packages/frontend/src/components/projects/project/settings/Domains.tsx +++ b/packages/frontend/src/components/projects/project/settings/Domains.tsx @@ -1,5 +1,5 @@ import React, { useMemo } from 'react'; -import { useParams, Link } from 'react-router-dom'; +import { useParams, Link, useOutletContext } from 'react-router-dom'; import { Button, Typography } from '@material-tailwind/react'; @@ -7,17 +7,21 @@ import DomainCard from './DomainCard'; import { DomainDetails } from '../../../../types/project'; import domainsData from '../../../../assets/domains.json'; import repositories from '../../../../assets/repositories.json'; -import projectData from '../../../../assets/projects.json'; const Domains = () => { const { id } = useParams(); + // @ts-expect-error create context type for projects + const { projects } = useOutletContext(); + const currProject = useMemo(() => { - return projectData.find((data) => data.id === Number(id)); + return projects.find((data: any) => Number(data.id) === Number(id)); }, [id]); const linkedRepo = useMemo(() => { - return repositories.find((repo) => repo.id === currProject?.repositoryId); + return repositories.find( + (repo) => repo.id === Number(currProject?.repositoryId), + ); }, [currProject]); return ( diff --git a/packages/frontend/src/layouts/ProjectSearch.tsx b/packages/frontend/src/layouts/ProjectSearch.tsx index e4928263..712a4420 100644 --- a/packages/frontend/src/layouts/ProjectSearch.tsx +++ b/packages/frontend/src/layouts/ProjectSearch.tsx @@ -1,17 +1,61 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Outlet } from 'react-router-dom'; import HorizontalLine from '../components/HorizontalLine'; import { IconButton, Typography } from '@material-tailwind/react'; import ProjectSearchBar from '../components/projects/ProjectSearchBar'; +import { useGQLClient } from '../context/GQLClientContext'; +import { ProjectDetails } from '../types/project'; const ProjectSearch = () => { + const client = useGQLClient(); + const [projects, setProjects] = useState([]); + + useEffect(() => { + const fetch = async () => { + const res = await client.getOrganizations(); + + // Note: select first organization as organization switching not yet implemented + const projects = res.organizations[0].projects; + const orgName = res.organizations[0].name; + + const updatedProjectsPromises = projects.map(async (project: any) => { + const { deployments } = await client.getDeployments(String(project.id)); + + return { + ...project, + // TODO: populate empty fields + icon: '', + title: project.name, + organization: orgName, + deployments, + url: '', + domain: null, + createdBy: project.owner.name, + source: '', + repositoryId: project.repository, + // TODO: populate from github API + latestCommit: { + message: '', + createdAt: '', + branch: '', + }, + }; + }); + + const updatedProjects = await Promise.all(updatedProjectsPromises); + setProjects(updatedProjects); + }; + + fetch(); + }, [client]); + return (
- {}} /> + {}} projects={projects} />
+ @@ -26,7 +70,7 @@ const ProjectSearch = () => {
- +
); diff --git a/packages/frontend/src/pages/index.tsx b/packages/frontend/src/pages/index.tsx index 5045a837..aec9075a 100644 --- a/packages/frontend/src/pages/index.tsx +++ b/packages/frontend/src/pages/index.tsx @@ -1,48 +1,14 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; +import { useOutletContext } from 'react-router-dom'; import { Link } from 'react-router-dom'; import { Button, Typography, Chip } from '@material-tailwind/react'; import ProjectCard from '../components/projects/ProjectCard'; -import projectsDetail from '../assets/projects.json'; -import { useGQLClient } from '../context/GQLClientContext'; const Projects = () => { - const client = useGQLClient(); - const [projects, setProjects] = useState([]); - - useEffect(() => { - const fetchOrganization = async () => { - const res = await client.getOrganizations(); - - // Note: select first organization as organization switching not yet implemented - const projects = res.organizations[0].projects; - - const updatedProjects = projects.map((project: any) => { - return { - ...project, - // TODO: populate empty fields - icon: '', - title: '', - organization: '', - url: '', - domain: null, - createdBy: '', - source: '', - // TODO: populate from github API - latestCommit: { - message: '', - createdAt: '', - branch: '', - }, - }; - }); - - setProjects(updatedProjects); - }; - - fetchOrganization(); - }, [client]); + // @ts-expect-error create context type for projects + const { projects } = useOutletContext(); return (
@@ -52,7 +18,7 @@ const Projects = () => { Projects
@@ -67,7 +33,7 @@ const Projects = () => {
{projects.length !== 0 && - projects.map((project, key) => { + projects.map((project: any, key: number) => { return ; })}
diff --git a/packages/frontend/src/pages/projects/Project.tsx b/packages/frontend/src/pages/projects/Project.tsx index 8536622f..f4115b16 100644 --- a/packages/frontend/src/pages/projects/Project.tsx +++ b/packages/frontend/src/pages/projects/Project.tsx @@ -1,22 +1,28 @@ import React, { useMemo } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; +import { useNavigate, useOutletContext, useParams } from 'react-router-dom'; import { Button, Typography } from '@material-tailwind/react'; import HorizontalLine from '../../components/HorizontalLine'; -import projects from '../../assets/projects.json'; import ProjectTabs from '../../components/projects/project/ProjectTabs'; -const getProject = (id: number) => { - return projects.find((project) => { - return project.id === id; +const getProject = (projects: any, id: number) => { + return projects.find((project: any) => { + return Number(project.id) === id; }); }; const Project = () => { const { id } = useParams(); const navigate = useNavigate(); - const project = useMemo(() => getProject(Number(id)), [id]); + + // @ts-expect-error create context type for projects + const { projects } = useOutletContext(); + + const project = useMemo( + () => getProject(projects, Number(id)), + [id, projects], + ); return (
diff --git a/packages/frontend/src/pages/projects/index.tsx b/packages/frontend/src/pages/projects/index.tsx index 3f181baf..07e9acb9 100644 --- a/packages/frontend/src/pages/projects/index.tsx +++ b/packages/frontend/src/pages/projects/index.tsx @@ -1,12 +1,14 @@ import React from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useOutletContext } from 'react-router-dom'; import { Button, Typography, Chip } from '@material-tailwind/react'; import ProjectCard from '../../components/projects/ProjectCard'; -import projectsDetail from '../../assets/projects.json'; const Projects = () => { + // @ts-expect-error create context type for projects + const { projects } = useOutletContext(); + return (
@@ -15,7 +17,7 @@ const Projects = () => { Projects
@@ -29,9 +31,10 @@ const Projects = () => {
- {projectsDetail.map((project, key) => { - return ; - })} + {projects.length !== 0 && + projects.map((project: any, key: number) => { + return ; + })}
); diff --git a/packages/frontend/src/types/project.ts b/packages/frontend/src/types/project.ts index 9c617afc..41e745f8 100644 --- a/packages/frontend/src/types/project.ts +++ b/packages/frontend/src/types/project.ts @@ -8,7 +8,7 @@ export interface ProjectDetails { id: number; createdAt: string; createdBy: string; - deployment: string; + deployments: DeploymentDetails[]; source: string; latestCommit: { message: string; @@ -30,6 +30,7 @@ export interface DeploymentDetails { isProduction: boolean; status: Status; branch: string; + isCurrent: boolean; commit: { hash: string; message: string; diff --git a/packages/gql-client/src/gql-client.ts b/packages/gql-client/src/gql-client.ts index b2f3627b..1962480d 100644 --- a/packages/gql-client/src/gql-client.ts +++ b/packages/gql-client/src/gql-client.ts @@ -1,6 +1,6 @@ import { ApolloClient, InMemoryCache, NormalizedCacheObject } from '@apollo/client'; -import { getUser, getOrganizations } from './gql-queries'; +import { getUser, getOrganizations, getDeployments } from './gql-queries'; export interface GraphQLConfig { gqlEndpoint: string; @@ -31,4 +31,15 @@ export class GQLClient { return data; } + + async getDeployments (projectId: string) : Promise { + const { data } = await this.client.query({ + query: getDeployments, + variables: { + projectId + } + }); + + return data; + } } diff --git a/packages/gql-client/src/gql-queries.ts b/packages/gql-client/src/gql-queries.ts index 565d7954..9422dbfa 100644 --- a/packages/gql-client/src/gql-queries.ts +++ b/packages/gql-client/src/gql-queries.ts @@ -15,10 +15,13 @@ query { export const getOrganizations = gql` query { organizations { + id + name projects { id owner { id + name } deployments { id @@ -42,3 +45,28 @@ query { } } `; + +export const getDeployments = gql` +query ($projectId: String!) { + deployments(projectId: $projectId) { + id + domain{ + branch + createdAt + isRedirected + id + name + status + updatedAt + } + branch + commitHash + title + environment + isCurrent + status + createdAt + updatedAt + } +} +`;