Add chips to display different kinds of information (#20)

* Add chip for showing deployment status

* Add chip to display projects count

* Display label if project search is not matching

* Add chip to display domain is not connected

* Fix text size in chips for deployment domain

* Add chip to display if repository is private

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2023-12-21 16:42:06 +05:30 committed by GitHub
parent 3133fb989f
commit 0a1a53e0bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 153 additions and 78 deletions

View File

@ -1,6 +1,6 @@
[
{
"title": "nextjs-bolerplate-9t44zbky4dg-bygideon-projects",
"title": "nextjs-boilerplate-9t44zbky4dg-bygideon-projects",
"status": "Building",
"environment": "Production",
"branch": "prod",
@ -12,7 +12,7 @@
"updatedAt": "2023-12-11T04:20:00"
},
{
"title": "nextjs-bolerplate-9232dwky4dg-bygideon-projects",
"title": "nextjs-boilerplate-9232dwky4dg-bygideon-projects",
"status": "Ready",
"environment": "Preview",
"branch": "prod",
@ -24,7 +24,7 @@
"updatedAt": "2023-12-11T04:20:00"
},
{
"title": "nextjs-bolerplate-9saa22y4dg-bygideon-projects",
"title": "nextjs-boilerplate-9saa22y4dg-bygideon-projects",
"status": "Error",
"environment": "Production",
"branch": "main",

View File

@ -4,8 +4,9 @@
"icon": "^",
"name": "iglotools",
"title": "Iglotools",
"domain": "",
"organization": "Airfoil",
"domain": "iglotools.co",
"url": "iglotools.co",
"createdAt": "2023-12-07T04:20:00",
"createdBy": "Alice",
"deployment": "iglotools.snowballtools.co",
@ -21,8 +22,9 @@
"icon": "^",
"name": "snowball-starter-kit",
"title": "Snowball Starter Kit",
"domain": "",
"organization": "Snowball",
"domain": "starterkit.snowballtools.com",
"url": "starterkit.snowballtools.com",
"createdAt": "2023-12-04T04:20:00",
"createdBy": "Bob",
"deployment": "deploy.snowballtools.com",
@ -38,8 +40,9 @@
"icon": "^",
"name": "web3-android",
"title": "Web3 Android",
"domain": "",
"organization": "Personal",
"domain": "web3fordroids.com",
"url": "web3fordroids.com",
"createdAt": "2023-12-01T04:20:00",
"createdBy": "Charlie",
"deployment": "deploy.web3fordroids.com",
@ -55,8 +58,9 @@
"icon": "^",
"name": "passkeys-demo",
"title": "Passkeys Demo",
"domain": "",
"organization": "Airfoil",
"domain": "passkeys.iglootools.xyz",
"url": "passkeys.iglootools.xyz",
"createdAt": "2023-12-01T04:20:00",
"createdBy": "David",
"deployment": "demo.passkeys.xyz",
@ -72,8 +76,9 @@
"icon": "^",
"name": "iglootools",
"title": "Iglootools",
"domain": "",
"organization": "Airfoil",
"domain": "iglotools.xyz",
"url": "iglotools.xyz",
"createdAt": "2023-12-11T04:20:00",
"createdBy": "Erin",
"deployment": "staging.snowballtools.com",
@ -89,8 +94,9 @@
"icon": "^",
"name": "iglootools",
"title": "Iglootools",
"domain": "",
"organization": "Airfoil",
"domain": "iglotools.xyz",
"url": "iglotools.xyz",
"createdAt": "2023-12-11T04:20:00",
"createdBy": "Frank",
"deployment": "iglotools.snowballtools.com",

View File

@ -2,31 +2,31 @@
{
"title": "project-101",
"updatedAt": "2023-12-21T08:30:00",
"user": "bob"
"user": "bob",
"private": false
},
{
"title": "project-102",
"updatedAt": "2023-12-21T08:30:00",
"user": "alice"
"user": "alice",
"private": true
},
{
"title": "project-103",
"updatedAt": "2023-12-21T04:20:00",
"user": "charlie"
"user": "charlie",
"private": false
},
{
"title": "project-104",
"updatedAt": "2023-12-21T04:27:00",
"user": "alice"
"user": "alice",
"private": false
},
{
"title": "project-105",
"updatedAt": "2023-12-21T04:41:00",
"user": "ivan"
},
{
"title": "project-106",
"updatedAt": "2023-12-21T04:32:00",
"user": "david"
"user": "ivan",
"private": false
}
]

View File

@ -25,7 +25,7 @@ const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
<Link to={`projects/${project.id}`}>
<Typography>{project.name}</Typography>
<Typography color="gray" variant="small">
{project.domain}
{project.url}
</Typography>
</Link>
</div>

View File

@ -27,6 +27,7 @@ const ProjectSearch = ({ onChange }: ProjectsSearchProps) => {
getInputProps,
getItemProps,
highlightedIndex,
inputValue,
} = useCombobox({
onInputValueChange({ inputValue }) {
setItems(
@ -57,39 +58,47 @@ const ProjectSearch = ({ onChange }: ProjectsSearchProps) => {
<div className="relative">
<SearchBar {...getInputProps()} />
<Card
className={`absolute w-1/2 max-h-100 -mt-1 overflow-y-scroll ${
!(isOpen && items.length) && 'hidden'
className={`absolute w-1/2 max-h-52 -mt-1 overflow-y-auto ${
(!inputValue || !isOpen) && 'hidden'
}`}
>
<List {...getMenuProps()}>
<div className="p-3">
<Typography variant="small" color="gray">
Suggestions
</Typography>
</div>
{items.map((item, index) => (
<ListItem
selected={highlightedIndex === index || selectedItem === item}
key={item.id}
{...getItemProps({ item, index })}
>
<ListItemPrefix>
<i>^</i>
</ListItemPrefix>
<div>
<Typography variant="h6" color="blue-gray">
{item.title}
</Typography>
<Typography
variant="small"
color="gray"
className="font-normal"
>
{item.organization}
{items.length ? (
<>
<div className="p-3">
<Typography variant="small" color="gray">
Suggestions
</Typography>
</div>
</ListItem>
))}
{items.map((item, index) => (
<ListItem
selected={highlightedIndex === index || selectedItem === item}
key={item.id}
{...getItemProps({ item, index })}
>
<ListItemPrefix>
<i>^</i>
</ListItemPrefix>
<div>
<Typography variant="h6" color="blue-gray">
{item.title}
</Typography>
<Typography
variant="small"
color="gray"
className="font-normal"
>
{item.organization}
</Typography>
</div>
</ListItem>
))}
</>
) : (
<div className="p-3">
<Typography>^ No projects matching this name</Typography>
</div>
)}
</List>
</Card>
</div>

View File

@ -1,6 +1,6 @@
import React from 'react';
import { IconButton } from '@material-tailwind/react';
import { Chip, IconButton } from '@material-tailwind/react';
import { relativeTime } from '../../../utils/time';
@ -8,6 +8,7 @@ interface RepositoryDetails {
title: string;
updatedAt: string;
user: string;
private: boolean;
}
interface ProjectRepoCardProps {
@ -19,9 +20,21 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
<div className="group flex items-center gap-4 text-gray-500 text-xs hover:bg-gray-100 p-2 cursor-pointer">
<div>^</div>
<div className="grow">
<p className="text-black">
{repository.user}/{repository.title}
</p>
<div>
<span className="text-black">
{repository.user}/{repository.title}
</span>
{repository.private ? (
<Chip
className="normal-case inline ml-6 bg-[#FED7AA] text-[#EA580C] font-normal"
size="sm"
value="Private"
icon={'^'}
/>
) : (
''
)}
</div>
<p>{relativeTime(repository.updatedAt)}</p>
</div>
<div className="hidden group-hover:block">

View File

@ -1,6 +1,6 @@
import React from 'react';
import { Typography } from '@material-tailwind/react';
import { Typography, IconButton } from '@material-tailwind/react';
import { relativeTime } from '../../../utils/time';
@ -18,7 +18,7 @@ interface ActivityCardProps {
const ActivityCard = ({ activity }: ActivityCardProps) => {
return (
<div className="flex hover:bg-gray-200 rounded mt-1">
<div className="group flex hover:bg-gray-200 rounded mt-1">
<div className="w-4">{activity.authorAvatar}</div>
<div className="grow">
@ -30,6 +30,11 @@ const ActivityCard = ({ activity }: ActivityCardProps) => {
{activity.message}
</Typography>
</div>
<div className="mr-2 self-center hidden group-hover:block">
<IconButton size="sm" className="rounded-full bg-gray-600">
{'>'}
</IconButton>
</div>
</div>
);
};

View File

@ -3,7 +3,9 @@ import React, { useCallback, useMemo, useState } from 'react';
import { Button, Typography } from '@material-tailwind/react';
import deploymentData from '../../../assets/deployments.json';
import DeployDetailsCard from './deployments/DeploymentDetailsCard';
import DeployDetailsCard, {
DeploymentDetails,
} from './deployments/DeploymentDetailsCard';
import FilterForm, {
FilterValue,
StatusOptions,
@ -17,7 +19,7 @@ const DEFAULT_FILTER_VALUE: FilterValue = {
const DeploymentsTabPanel = () => {
const [filterValue, setFilterValue] = useState(DEFAULT_FILTER_VALUE);
const filteredDeployments = useMemo(() => {
const filteredDeployments = useMemo<DeploymentDetails[]>(() => {
return deploymentData.filter((deployment) => {
// Searched branch filter
const branchMatch =
@ -37,7 +39,7 @@ const DeploymentsTabPanel = () => {
new Date(deployment.updatedAt) <= filterValue.updateAtRange!.to!);
return branchMatch && statusMatch && dateMatch;
});
}) as DeploymentDetails[];
}, [filterValue]);
const handleResetFilters = useCallback(() => {

View File

@ -1,6 +1,6 @@
import React from 'react';
import { Typography } from '@material-tailwind/react';
import { Typography, Button, Chip } from '@material-tailwind/react';
import ActivityCard from './ActivityCard';
import activityDetails from '../../../assets/activities.json';
@ -19,24 +19,40 @@ const OverviewTabPanel = ({ project }: OverviewProps) => (
<div className="grow">
<Typography>{project.name}</Typography>
<Typography variant="small" color="gray">
{project.domain}
{project.url}
</Typography>
</div>
</div>
<div className="flex justify-between p-2 text-sm">
<p>Domain</p>
{project.domain ? <p>{project.domain}</p> : <button>Set up</button>}
<div className="flex justify-between p-2 text-sm items-center">
<div>
^ Domain
{!project.domain && (
<Chip
className="normal-case ml-6 bg-[#FED7AA] text-[#EA580C] inline font-normal"
size="sm"
value="Not connected"
icon="^"
/>
)}
</div>
{project.domain ? (
<p>{project.domain}</p>
) : (
<Button className="normal-case rounded-full" color="blue" size="sm">
Setup
</Button>
)}
</div>
<div className="flex justify-between p-2 text-sm">
<p>Source</p>
<p>^ {project.source}</p>
<p>^ Source</p>
<p>{project.source}</p>
</div>
<div className="flex justify-between p-2 text-sm">
<p>deployment</p>
<p>{project.deployment} ^</p>
<p>^ Deployment</p>
<p className="text-blue-600">{project.deployment}</p>
</div>
<div className="flex justify-between p-2 text-sm">
<p>Created</p>
<p>^ Created</p>
<p>
{relativeTime(project.createdAt)} by ^ {project.createdBy}
</p>

View File

@ -6,13 +6,21 @@ import {
MenuList,
MenuItem,
Typography,
Chip,
ChipProps,
} from '@material-tailwind/react';
import { relativeTime } from '../../../../utils/time';
interface DeploymentDetails {
export enum Status {
BUILDING = 'Building',
READY = 'Ready',
ERROR = 'Error',
}
export interface DeploymentDetails {
title: string;
status: string;
status: Status;
environment: string;
branch: string;
commit: {
@ -27,15 +35,24 @@ interface DeployDetailsCardProps {
deployment: DeploymentDetails;
}
const STATUS_COLORS: { [key in Status]: ChipProps['color'] } = {
[Status.BUILDING]: 'blue',
[Status.READY]: 'green',
[Status.ERROR]: 'red',
};
const DeployDetailsCard = ({ deployment }: DeployDetailsCardProps) => {
return (
<div className="grid grid-cols-4 gap-2 border-b border-gray-300">
<div className="grid grid-cols-4 gap-2 border-b border-gray-300 p-3 my-2">
<div className="col-span-2">
<div className="flex">
<Typography className=" basis-2/3">{deployment.title}</Typography>
<Typography color="gray" className="basis-1/3">
{deployment.status}
</Typography>
<Typography className=" basis-3/4">{deployment.title}</Typography>
<Chip
value={deployment.status}
color={STATUS_COLORS[deployment.status] ?? 'gray'}
variant="ghost"
icon={<i>^</i>}
/>
</div>
<Typography color="gray">{deployment.environment}</Typography>
</div>

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Button, IconButton, Typography } from '@material-tailwind/react';
import { Button, IconButton, Typography, Chip } from '@material-tailwind/react';
import ProjectCard from '../components/projects/ProjectCard';
import HorizontalLine from '../components/HorizontalLine';
@ -26,12 +26,18 @@ const Projects = () => {
</div>
</div>
<HorizontalLine />
<div className="flex p-4">
<div className="flex p-5">
<div className="grow">
<Typography variant="h4">Projects</Typography>
<div className="flex gap-2 items-center">
<Typography variant="h4">Projects</Typography>
<Chip
className="bg-gray-300 rounded-full static"
value={projectsDetail.length}
size="sm"
/>
</div>
</div>
<div>
{/* TODO: Create button component */}
<Link to="/projects/create">
<Button className="rounded-full" color="blue">
Create project

View File

@ -3,6 +3,7 @@ export interface ProjectDetails {
name: string;
title: string;
organization: string;
url: string;
domain: string;
id: number;
createdAt: string;