[7/n][project settings ui] ProjectSettingContainer (#33)
This commit is contained in:
commit
690fc8d2cb
@ -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 };
|
@ -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 };
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
<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.
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user