Add layout for overview panel in project details page (#3)
* Create layout for overview panel * Populate project details in overview panel * Add more types * Fix typo --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
348ff92fa9
commit
5a17747be2
37
packages/frontend/src/assets/activities.json
Normal file
37
packages/frontend/src/assets/activities.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"author": "Bob",
|
||||||
|
"authorAvatar": "^",
|
||||||
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
|
"branch": "main",
|
||||||
|
"message": "Design integrate and tested"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Alice",
|
||||||
|
"authorAvatar": "^",
|
||||||
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
|
"branch": "prod",
|
||||||
|
"message": "Fix lint errors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Charlie",
|
||||||
|
"authorAvatar": "^",
|
||||||
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
|
"branch": "main",
|
||||||
|
"message": "Sidebar changed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Roy",
|
||||||
|
"authorAvatar": "^",
|
||||||
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
|
"branch": "staging",
|
||||||
|
"message": "Add style to the page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Brad",
|
||||||
|
"authorAvatar": "^",
|
||||||
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
|
"branch": "dev",
|
||||||
|
"message": "404 not found"
|
||||||
|
}
|
||||||
|
]
|
@ -4,9 +4,13 @@
|
|||||||
"icon": "^",
|
"icon": "^",
|
||||||
"title": "iglotools",
|
"title": "iglotools",
|
||||||
"domain": "iglotools.com",
|
"domain": "iglotools.com",
|
||||||
|
"createdAt": "2023-12-07T04:20:00",
|
||||||
|
"createdBy": "Bob",
|
||||||
|
"deployment": "iglotools.snowball.com",
|
||||||
|
"source": "feature/add-remote-control",
|
||||||
"latestCommit": {
|
"latestCommit": {
|
||||||
"message": "Subscription added",
|
"message": "Subscription added",
|
||||||
"time": "2023-12-11T04:20:00",
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
"branch": "main"
|
"branch": "main"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -15,9 +19,13 @@
|
|||||||
"icon": "^",
|
"icon": "^",
|
||||||
"title": "snowball-starter-kit",
|
"title": "snowball-starter-kit",
|
||||||
"domain": "snowball-starter-kit.com",
|
"domain": "snowball-starter-kit.com",
|
||||||
|
"createdAt": "2023-12-04T04:20:00",
|
||||||
|
"createdBy": "Erin",
|
||||||
|
"deployment": "snowball-starter-kit.com",
|
||||||
|
"source": "prod/add-docker-compose",
|
||||||
"latestCommit": {
|
"latestCommit": {
|
||||||
"message": "404 added",
|
"message": "404 added",
|
||||||
"time": "2023-12-11T04:20:00",
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
"branch": "staging"
|
"branch": "staging"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -26,9 +34,13 @@
|
|||||||
"icon": "^",
|
"icon": "^",
|
||||||
"title": "passkeys-demo",
|
"title": "passkeys-demo",
|
||||||
"domain": "passkeys-demo.com",
|
"domain": "passkeys-demo.com",
|
||||||
|
"createdAt": "2023-12-01T04:20:00",
|
||||||
|
"createdBy": "Charlie",
|
||||||
|
"deployment": "passkeys-demo.com",
|
||||||
|
"source": "dev/style-page",
|
||||||
"latestCommit": {
|
"latestCommit": {
|
||||||
"message": "Design system integrated",
|
"message": "Design system integrated",
|
||||||
"time": "2023-12-11T04:20:00",
|
"createdAt": "2023-12-01T04:20:00",
|
||||||
"branch": "main"
|
"branch": "main"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -37,9 +49,13 @@
|
|||||||
"icon": "^",
|
"icon": "^",
|
||||||
"title": "watcher-tool",
|
"title": "watcher-tool",
|
||||||
"domain": "azimuth-watcher.com",
|
"domain": "azimuth-watcher.com",
|
||||||
|
"createdAt": "2023-12-11T04:20:00",
|
||||||
|
"createdBy": "Alice",
|
||||||
|
"deployment": "azimuth-watcher.com",
|
||||||
|
"source": "prod/fix-error",
|
||||||
"latestCommit": {
|
"latestCommit": {
|
||||||
"message": "Listen for subscription",
|
"message": "Listen for subscription",
|
||||||
"time": "2023-12-10T04:20:00",
|
"createdAt": "2023-12-09T04:20:00",
|
||||||
"branch": "prod"
|
"branch": "prod"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
packages/frontend/src/components/ActivityCard.tsx
Normal file
33
packages/frontend/src/components/ActivityCard.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { relativeTime } from '../utils/time';
|
||||||
|
|
||||||
|
interface ActivityDetails {
|
||||||
|
author: string;
|
||||||
|
authorAvatar: string;
|
||||||
|
createdAt: string;
|
||||||
|
branch: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActivityCardProps {
|
||||||
|
activity: ActivityDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActivityCard = ({ activity }: ActivityCardProps) => {
|
||||||
|
return (
|
||||||
|
<div className="flex hover:bg-gray-200 rounded mt-1">
|
||||||
|
<div className="w-4">{activity.authorAvatar}</div>
|
||||||
|
|
||||||
|
<div className="grow text-sm text-gray-500">
|
||||||
|
<p className="text-black">{activity.author}</p>
|
||||||
|
<p className="text-xs">
|
||||||
|
{relativeTime(activity.createdAt)} ^ {activity.branch}
|
||||||
|
</p>
|
||||||
|
<p>{activity.message}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActivityCard;
|
57
packages/frontend/src/components/Overview.tsx
Normal file
57
packages/frontend/src/components/Overview.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import ActivityCard from './ActivityCard';
|
||||||
|
import activityDetails from '../assets/activities.json';
|
||||||
|
import { ProjectDetails } from '../types/project';
|
||||||
|
import { relativeTime } from '../utils/time';
|
||||||
|
|
||||||
|
interface OverviewProps {
|
||||||
|
project: ProjectDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Overview = ({ project }: OverviewProps) => (
|
||||||
|
<div className="grid grid-cols-5">
|
||||||
|
<div className="col-span-3 p-2">
|
||||||
|
<div className="flex items-center gap-2 p-2 ">
|
||||||
|
<div>^</div>
|
||||||
|
<div className="grow">
|
||||||
|
<p className="text-sm text-gray-700">{project.title}</p>
|
||||||
|
<p className="text-sm text-gray-400">{project.domain}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between p-2 text-sm">
|
||||||
|
<p>Domain</p>
|
||||||
|
<button>Set up</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between p-2 text-sm">
|
||||||
|
<p>Source</p>
|
||||||
|
<p>{project.source}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between p-2 text-sm">
|
||||||
|
<p>deployment</p>
|
||||||
|
<p>{project.deployment}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between p-2 text-sm">
|
||||||
|
<p>Created</p>
|
||||||
|
<p>
|
||||||
|
{relativeTime(project.createdAt)} by {project.createdBy}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2 p-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<p>Activity</p>
|
||||||
|
<button className="text-xs bg-gray-300 rounded-full p-2">
|
||||||
|
See all
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="p-2">
|
||||||
|
{activityDetails.map((activity, key) => {
|
||||||
|
return <ActivityCard activity={activity} key={key} />;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Overview;
|
@ -1,19 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
interface projectDetails {
|
import { relativeTime } from '../utils/time';
|
||||||
icon: string;
|
import { ProjectDetails } from '../types/project';
|
||||||
title: string;
|
|
||||||
domain: string;
|
|
||||||
id: number;
|
|
||||||
latestCommit: {
|
|
||||||
[key: string]: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProjectCardProps {
|
interface ProjectCardProps {
|
||||||
project: projectDetails;
|
project: ProjectDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
|
const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
|
||||||
@ -32,7 +24,7 @@ const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
|
|||||||
<div className="border-slate-200 border-t-2 border-solid p-4 text-gray-500 text-xs">
|
<div className="border-slate-200 border-t-2 border-solid p-4 text-gray-500 text-xs">
|
||||||
<p>{project.latestCommit.message}</p>
|
<p>{project.latestCommit.message}</p>
|
||||||
<p>
|
<p>
|
||||||
{DateTime.fromISO(project.latestCommit.time).toRelative()} on{' '}
|
{relativeTime(project.latestCommit.createdAt)} on{' '}
|
||||||
{project.latestCommit.branch}
|
{project.latestCommit.branch}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
|
import { relativeTime } from '../utils/time';
|
||||||
|
|
||||||
interface RepositoryDetails {
|
interface RepositoryDetails {
|
||||||
title: string;
|
title: string;
|
||||||
@ -16,7 +17,7 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
|||||||
<div>^</div>
|
<div>^</div>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<p>{repository.title}</p>
|
<p>{repository.title}</p>
|
||||||
<p>{DateTime.fromISO(repository.updatedTime).toRelative()}</p>
|
<p>{relativeTime(repository.updatedTime)}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
||||||
|
|
||||||
const Overview = () => (
|
import Overview from './Overview';
|
||||||
<div>
|
import { ProjectDetails } from '../types/project';
|
||||||
Content of overview tab
|
|
||||||
<p className="block">
|
interface ProjectTabsProps {
|
||||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
|
project: ProjectDetails;
|
||||||
</p>
|
}
|
||||||
</div>
|
|
||||||
);
|
|
||||||
const Deployments = () => (
|
const Deployments = () => (
|
||||||
<div>
|
<div>
|
||||||
Content of deployments tab
|
Content of deployments tab
|
||||||
@ -44,7 +43,7 @@ const Settings = () => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ProjectTab = () => {
|
const ProjectTabs = ({ project }: ProjectTabsProps) => {
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
selectedTabClassName={
|
selectedTabClassName={
|
||||||
@ -59,7 +58,7 @@ const ProjectTab = () => {
|
|||||||
<Tab className={'p-2 cursor-pointer'}>Settings</Tab>
|
<Tab className={'p-2 cursor-pointer'}>Settings</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<Overview />
|
<Overview project={project} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<Deployments />
|
<Deployments />
|
||||||
@ -77,4 +76,4 @@ const ProjectTab = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProjectTab;
|
export default ProjectTabs;
|
||||||
|
@ -6,7 +6,7 @@ import TemplateCard from '../../components/TemplateCard';
|
|||||||
import RepositoryList from '../../components/RepositoryList';
|
import RepositoryList from '../../components/RepositoryList';
|
||||||
import ConnectAccount from '../../components/ConnectAccount';
|
import ConnectAccount from '../../components/ConnectAccount';
|
||||||
|
|
||||||
const isGitAuth = true;
|
const IS_GIT_AUTH = true;
|
||||||
|
|
||||||
const CreateProject = () => {
|
const CreateProject = () => {
|
||||||
return (
|
return (
|
||||||
@ -31,7 +31,7 @@ const CreateProject = () => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<h5 className="mt-4 ml-4">Import a repository</h5>
|
<h5 className="mt-4 ml-4">Import a repository</h5>
|
||||||
{isGitAuth ? <RepositoryList /> : <ConnectAccount />}
|
{IS_GIT_AUTH ? <RepositoryList /> : <ConnectAccount />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom';
|
|||||||
|
|
||||||
import HorizontalLine from '../../components/HorizontalLine';
|
import HorizontalLine from '../../components/HorizontalLine';
|
||||||
import projects from '../../assets/projects.json';
|
import projects from '../../assets/projects.json';
|
||||||
import ProjectTab from '../../components/Tab';
|
import ProjectTabs from '../../components/Tab';
|
||||||
|
|
||||||
const getProject = (id: number) => {
|
const getProject = (id: number) => {
|
||||||
return projects.find((project) => {
|
return projects.find((project) => {
|
||||||
@ -18,6 +18,8 @@ const Project = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white rounded-3xl h-full">
|
<div className="bg-white rounded-3xl h-full">
|
||||||
|
{project ? (
|
||||||
|
<>
|
||||||
<div className="flex p-4 gap-4">
|
<div className="flex p-4 gap-4">
|
||||||
<button onClick={() => navigate(-1)}>{'<'}</button>
|
<button onClick={() => navigate(-1)}>{'<'}</button>
|
||||||
<h3 className="grow">{project?.title} </h3>
|
<h3 className="grow">{project?.title} </h3>
|
||||||
@ -26,8 +28,12 @@ const Project = () => {
|
|||||||
</div>
|
</div>
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<ProjectTab />
|
<ProjectTabs project={project} />
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<h4>Project not found</h4>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
15
packages/frontend/src/types/project.ts
Normal file
15
packages/frontend/src/types/project.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export interface ProjectDetails {
|
||||||
|
icon: string;
|
||||||
|
title: string;
|
||||||
|
domain: string;
|
||||||
|
id: number;
|
||||||
|
createdAt: string;
|
||||||
|
createdBy: string;
|
||||||
|
deployment: string;
|
||||||
|
source: string;
|
||||||
|
latestCommit: {
|
||||||
|
message: string;
|
||||||
|
createdAt: string;
|
||||||
|
branch: string;
|
||||||
|
};
|
||||||
|
}
|
11
packages/frontend/src/utils/time.ts
Normal file
11
packages/frontend/src/utils/time.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an ISO 8601 formatted time to a human-readable relative time with respect to the current time.
|
||||||
|
*
|
||||||
|
* @param {string} time - The input time in ISO 8601 format.
|
||||||
|
* @returns {string} - A human-readable relative time string.
|
||||||
|
*/
|
||||||
|
export const relativeTime = (time: string) => {
|
||||||
|
return DateTime.fromISO(time).toRelative();
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user