[7/n][project settings ui] ProjectSettingContainer (#33)

This commit is contained in:
Vivian Phung 2024-05-14 16:13:28 -04:00 committed by GitHub
commit 690fc8d2cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 116 additions and 66 deletions

View File

@ -0,0 +1,32 @@
import { PropsWithChildren } from 'react';
import { ProjectSettingHeader } from './ProjectSettingHeader';
export interface ProjectSettingContainerProps extends PropsWithChildren {
headingText: string;
className?: string;
button?: React.ReactNode;
badge?: React.ReactNode;
}
const ProjectSettingContainer: React.FC<ProjectSettingContainerProps> = ({
headingText,
className,
button,
children,
badge,
...props
}: ProjectSettingContainerProps) => {
return (
<div className={'flex-col justify-start gap-8 space-y-3 px-2'} {...props}>
<ProjectSettingHeader
headingText={headingText}
button={button}
badge={badge}
/>
{children}
</div>
);
};
export { ProjectSettingContainer };

View File

@ -0,0 +1,30 @@
import { PropsWithChildren } from 'react';
import { Heading } from 'components/shared/Heading';
export interface ProjectSettingHeaderProps extends PropsWithChildren {
headingText: string;
button?: React.ReactNode;
badge?: React.ReactNode;
}
const ProjectSettingHeader: React.FC<ProjectSettingHeaderProps> = ({
headingText,
button,
badge,
...props
}) => {
return (
<div className="flex justify-between items-center" {...props}>
<div className="flex space-x-2 items-center">
<Heading className="text-lg font-medium leading-normal">
{headingText}
</Heading>
{badge}
</div>
{button ?? button}
</div>
);
};
export { ProjectSettingHeader };

View File

@ -6,11 +6,11 @@ import MemberCard from 'components/projects/project/settings/MemberCard';
import AddMemberDialog from 'components/projects/project/settings/AddMemberDialog';
import { useGQLClient } from '../../../../../context/GQLClientContext';
import { OutletContextType } from '../../../../../types';
import { useToast } from 'components/shared/Toast';
import { useToast } from '../../../../../components/shared/Toast';
import { Button } from 'components/shared/Button';
import { PlusIcon } from 'components/shared/CustomIcon';
import { Badge } from 'components/shared/Badge';
import { Heading } from 'components/shared/Heading';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';
const FIRST_MEMBER_CARD = 0;
@ -105,16 +105,14 @@ const CollaboratorsTabPanel = () => {
}, [project.id, fetchProjectMembers]);
return (
<div className="space-y-3 px-2">
<div className="flex justify-between">
<div className="flex space-x-2">
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Collaborators
</Heading>
<Badge size="sm" variant="inset">
{projectMembers.length + 1}
</Badge>
</div>
<ProjectSettingContainer
headingText="Collaborators"
badge={
<Badge size="sm" variant="inset">
{projectMembers.length + 1}
</Badge>
}
button={
<Button
size="md"
onClick={() => setAddMemberDialogOpen((preVal) => !preVal)}
@ -123,7 +121,8 @@ const CollaboratorsTabPanel = () => {
>
Add member
</Button>
</div>
}
>
<MemberCard
member={project.owner}
isFirstCard={true}
@ -156,7 +155,7 @@ const CollaboratorsTabPanel = () => {
open={addmemberDialogOpen}
handleAddMember={addMemberHandler}
/>
</div>
</ProjectSettingContainer>
);
};

View File

@ -7,8 +7,9 @@ import DomainCard from 'components/projects/project/settings/DomainCard';
import { useGQLClient } from '../../../../../context/GQLClientContext';
import { OutletContextType } from '../../../../../types';
import { useOctokit } from '../../../../../context/OctokitContext';
import { Heading } from 'components/shared/Heading';
import { Button } from 'components/shared/Button';
import { PlusIcon } from 'components/shared/CustomIcon';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';
const Domains = () => {
const client = useGQLClient();
@ -57,16 +58,20 @@ const Domains = () => {
}, []);
return (
<>
<div className="space-y-3 px-2">
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Domains
</Heading>
<Button as="a" href="add">
<ProjectSettingContainer
headingText="Domains"
button={
<Button
as="a"
href="add"
variant="secondary"
leftIcon={<PlusIcon />}
size="md"
>
Add domain
</Button>
</div>
}
>
{domains.map((domain) => {
return (
<DomainCard
@ -80,7 +85,7 @@ const Domains = () => {
/>
);
})}
</>
</ProjectSettingContainer>
);
};

View File

@ -16,6 +16,7 @@ import { Button } from 'components/shared/Button';
import { Checkbox } from 'components/shared/Checkbox';
import { PlusIcon } from 'components/shared/CustomIcon';
import { InlineNotification } from 'components/shared/InlineNotification';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';
export const EnvironmentVariablesTabPanel = () => {
const { id } = useParams();
@ -130,10 +131,7 @@ export const EnvironmentVariablesTabPanel = () => {
);
return (
<div className="space-y-3 px-2">
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Environment variables
</Heading>
<ProjectSettingContainer headingText="Environment variables">
<p className="text-slate-600 text-sm font-normal leading-tight">
A new deployment is required for your changes to take effect.
</p>
@ -236,6 +234,6 @@ export const EnvironmentVariablesTabPanel = () => {
}}
/>
</div>
</div>
</ProjectSettingContainer>
);
};

View File

@ -12,6 +12,7 @@ import { Button } from 'components/shared/Button';
import { Select, SelectOption } from 'components/shared/Select';
import { TrashIcon, CopyUnfilledIcon } from 'components/shared/CustomIcon';
import { useToast } from 'components/shared/Toast';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';
const GeneralTabPanel = () => {
const client = useGQLClient();
@ -109,7 +110,7 @@ const GeneralTabPanel = () => {
}, [project]);
return (
<div className="flex-col justify-start items-start gap-6 inline-flex">
<ProjectSettingContainer headingText="Project Info">
<form
onSubmit={handleSubmit(async ({ appName, description }) => {
const { updateProject } = await client.updateProject(project.id, {
@ -120,11 +121,8 @@ const GeneralTabPanel = () => {
await onUpdate();
}
})}
className="self-stretch space-y-3 px-2"
className="self-stretch space-y-3"
>
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Project Info
</Heading>
<Input
// TODO: Debug issue: https://github.com/creativetimofficial/material-tailwind/issues/427
label="App name"
@ -221,7 +219,7 @@ const GeneralTabPanel = () => {
project={project}
/>
</div>
</div>
</ProjectSettingContainer>
);
};

View File

@ -8,8 +8,9 @@ import { OutletContextType } from '../../../../../types';
import { Button } from 'components/shared/Button';
import { Input } from 'components/shared/Input';
import { Switch } from 'components/shared/Switch';
import { Heading } from 'components/shared/Heading';
import { useToast } from 'components/shared/Toast';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';
import { ProjectSettingHeader } from 'components/projects/project/settings/ProjectSettingHeader';
type UpdateProdBranchValues = {
prodBranch: string;
@ -134,12 +135,8 @@ const GitTabPanel = () => {
};
return (
<div className="flex-col justify-start items-start gap-6 inline-flex">
<div className="self-stretch space-y-3 px-2">
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Git repository
</Heading>
<ProjectSettingContainer headingText="Git repository">
<div className="self-stretch space-y-3">
<div className="flex justify-between mt-4">
<div>
<p className="text-slate-600 text-sm font-normal leading-tight">
@ -171,11 +168,9 @@ const GitTabPanel = () => {
<form
onSubmit={handleSubmitProdBranch(updateProdBranchHandler)}
className="space-y-3 px-2"
className="space-y-3"
>
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Production branch
</Heading>
<ProjectSettingHeader headingText="Production branch" />
<p className="text-slate-600 text-sm font-normal leading-tight">
By default, each commit pushed to the{' '}
<span className="font-bold">{project.prodBranch}</span> branch
@ -193,11 +188,9 @@ const GitTabPanel = () => {
<form
onSubmit={handleSubmitWebhooks(updateWebhooksHandler)}
className="space-y-3 px-2"
className="space-y-3"
>
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Deploy webhooks
</Heading>
<ProjectSettingHeader headingText="Deploy webhooks" />
<p className="text-slate-600 text-sm font-normal leading-tight">
{' '}
Webhooks configured to trigger when there is a change in a
@ -228,7 +221,7 @@ const GitTabPanel = () => {
);
})}
</div>
</div>
</ProjectSettingContainer>
);
};

View File

@ -2,11 +2,11 @@ import toast from 'react-hot-toast';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { useGQLClient } from '../../../../../../../context/GQLClientContext';
import { Heading } from 'components/shared/Heading';
import { Table } from 'components/shared/Table';
import { Button } from 'components/shared/Button';
import { InlineNotification } from 'components/shared/InlineNotification';
import { ArrowRightCircleIcon } from 'components/shared/CustomIcon';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';
const Config = () => {
const { id, orgSlug } = useParams();
@ -40,18 +40,13 @@ const Config = () => {
// TODO: Figure out DNS Provider if possible and update appropriatly
return (
<div className="flex flex-col gap-6 w-full">
<div>
<Heading className="text-sky-950 text-lg font-medium leading-normal">
Setup domain name
</Heading>
<p className="text-blue-gray-500">
Add the following records to your domain.&nbsp;
<a href="https://www.namecheap.com/" target="_blank" rel="noreferrer">
<span className="underline">Go to NameCheap</span>
</a>
</p>
</div>
<ProjectSettingContainer headingText="Setup domain name">
<p className="text-blue-gray-500">
Add the following records to your domain.&nbsp;
<a href="https://www.namecheap.com/" target="_blank" rel="noreferrer">
<span className="underline">Go to NameCheap</span>
</a>
</p>
<Table>
<Table.Header>
@ -90,7 +85,7 @@ const Config = () => {
>
Finish
</Button>
</div>
</ProjectSettingContainer>
);
};

View File

@ -5,7 +5,7 @@ import {
IconButton,
} from '@snowballtools/material-tailwind-react-fork';
import Stepper from '../../../../../../../components/Stepper';
import Stepper from 'components/Stepper';
const AddDomain = () => {
const { id, orgSlug } = useParams();