mirror of
https://github.com/snowball-tools/snowballtools-base.git
synced 2024-12-22 16:37:44 +00:00
[7/n][project settings ui] AddEnvironmentVariableRowProps Input (#29)
This commit is contained in:
commit
abbda18fc7
@ -1,10 +1,9 @@
|
||||
import { UseFormRegister } from 'react-hook-form';
|
||||
|
||||
import { Input } from 'components/shared/Input';
|
||||
|
||||
import { EnvironmentVariablesFormValues } from '../../../../types';
|
||||
import { Button } from 'components/shared/Button';
|
||||
import { TrashIcon } from 'components/shared/CustomIcon';
|
||||
import { Input } from 'components/shared/Input';
|
||||
|
||||
interface AddEnvironmentVariableRowProps {
|
||||
onDelete: () => void;
|
||||
@ -20,28 +19,24 @@ const AddEnvironmentVariableRow = ({
|
||||
isDeleteDisabled,
|
||||
}: AddEnvironmentVariableRowProps) => {
|
||||
return (
|
||||
<div className="flex gap-1 p-2">
|
||||
<div>
|
||||
<Input
|
||||
label="key"
|
||||
size="sm"
|
||||
{...register(`variables.${index}.key`, {
|
||||
required: 'Key field cannot be empty',
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Input
|
||||
size="sm"
|
||||
label="value"
|
||||
{...register(`variables.${index}.value`, {
|
||||
required: 'Value field cannot be empty',
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-1 py-4 self-stretch">
|
||||
<Input
|
||||
size="md"
|
||||
{...register(`variables.${index}.key`, {
|
||||
required: 'Key field cannot be empty',
|
||||
})}
|
||||
label={index === 0 ? 'Key' : undefined}
|
||||
/>
|
||||
<Input
|
||||
size="md"
|
||||
label={index === 0 ? 'Value' : undefined}
|
||||
{...register(`variables.${index}.value`, {
|
||||
required: 'Value field cannot be empty',
|
||||
})}
|
||||
/>
|
||||
<div className="self-end">
|
||||
<Button
|
||||
size="sm"
|
||||
size="md"
|
||||
iconOnly
|
||||
onClick={() => onDelete()}
|
||||
disabled={isDeleteDisabled}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
import { Project } from 'gql-client';
|
||||
|
||||
import {
|
||||
@ -13,7 +12,9 @@ import {
|
||||
Input,
|
||||
Typography,
|
||||
} from '@snowballtools/material-tailwind-react-fork';
|
||||
|
||||
import { useGQLClient } from '../../../../context/GQLClientContext';
|
||||
import { useToast } from 'components/shared/Toast';
|
||||
|
||||
interface DeleteProjectDialogProp {
|
||||
open: boolean;
|
||||
@ -26,6 +27,7 @@ const DeleteProjectDialog = ({
|
||||
handleOpen,
|
||||
project,
|
||||
}: DeleteProjectDialogProp) => {
|
||||
const { toast, dismiss } = useToast();
|
||||
const { orgSlug } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const client = useGQLClient();
|
||||
@ -46,7 +48,12 @@ const DeleteProjectDialog = ({
|
||||
if (deleteProject) {
|
||||
navigate(`/${orgSlug}`);
|
||||
} else {
|
||||
toast.error('Project not deleted');
|
||||
toast({
|
||||
id: 'project_not_deleted',
|
||||
title: 'Project not deleted',
|
||||
variant: 'error',
|
||||
onDismiss: dismiss,
|
||||
});
|
||||
}
|
||||
|
||||
handleOpen();
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Collapse,
|
||||
Typography,
|
||||
} from '@snowballtools/material-tailwind-react-fork';
|
||||
import { Collapse } from '@snowballtools/material-tailwind-react-fork';
|
||||
|
||||
import EditEnvironmentVariableRow from './EditEnvironmentVariableRow';
|
||||
import { Environment, EnvironmentVariable } from 'gql-client';
|
||||
import {
|
||||
ChevronDownSmallIcon,
|
||||
ChevronUpSmallIcon,
|
||||
} from 'components/shared/CustomIcon';
|
||||
|
||||
interface DisplayEnvironmentVariablesProps {
|
||||
environment: Environment;
|
||||
@ -24,23 +24,19 @@ const DisplayEnvironmentVariables = ({
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="flex gap-4 p-2 "
|
||||
className="flex gap-4 p-2"
|
||||
onClick={() => setOpenCollapse((cur) => !cur)}
|
||||
>
|
||||
<div>^</div>
|
||||
{openCollapse ? <ChevronUpSmallIcon /> : <ChevronDownSmallIcon />}
|
||||
<div className="grow capitalize">{environment}</div>
|
||||
<div>{variables.length} variables</div>
|
||||
</div>
|
||||
<Collapse open={openCollapse}>
|
||||
{variables.length === 0 ? (
|
||||
<Card className="bg-gray-300 flex items-center p-4">
|
||||
<Typography variant="small" className="text-black">
|
||||
No environment variables added yet.
|
||||
</Typography>
|
||||
<Typography variant="small">
|
||||
Once you add them, they’ll show up here.
|
||||
</Typography>
|
||||
</Card>
|
||||
<div className="bg-slate-100 rounded-xl flex-col p-4">
|
||||
No environment variables added yet. Once you add them, they'll show
|
||||
up here.
|
||||
</div>
|
||||
) : (
|
||||
variables.map((variable: EnvironmentVariable) => {
|
||||
return (
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { Domain, DomainStatus, Project } from 'gql-client';
|
||||
|
||||
import {
|
||||
@ -15,6 +14,7 @@ import {
|
||||
import EditDomainDialog from './EditDomainDialog';
|
||||
import { useGQLClient } from 'context/GQLClientContext';
|
||||
import { DeleteDomainDialog } from 'components/projects/Dialog/DeleteDomainDialog';
|
||||
import { useToast } from 'components/shared/Toast';
|
||||
|
||||
enum RefreshStatus {
|
||||
IDLE,
|
||||
@ -47,6 +47,7 @@ const DomainCard = ({
|
||||
project,
|
||||
onUpdate,
|
||||
}: DomainCardProps) => {
|
||||
const { toast, dismiss } = useToast();
|
||||
const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE);
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
||||
@ -58,9 +59,19 @@ const DomainCard = ({
|
||||
|
||||
if (deleteDomain) {
|
||||
onUpdate();
|
||||
toast.success(`Domain ${domain.name} deleted successfully`);
|
||||
toast({
|
||||
id: 'domain_deleted_success',
|
||||
title: 'Domain deleted',
|
||||
variant: 'success',
|
||||
onDismiss: dismiss,
|
||||
});
|
||||
} else {
|
||||
toast.error(`Error deleting domain ${domain.name}`);
|
||||
toast({
|
||||
id: 'domain_deleted_error',
|
||||
title: `Error deleting domain ${domain.name}`,
|
||||
variant: 'error',
|
||||
onDismiss: dismiss,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,12 +5,12 @@ import { EnvironmentVariable } from 'gql-client';
|
||||
|
||||
import {
|
||||
IconButton,
|
||||
Input,
|
||||
Typography,
|
||||
} from '@snowballtools/material-tailwind-react-fork';
|
||||
|
||||
import { useGQLClient } from 'context/GQLClientContext';
|
||||
import { DeleteVariableDialog } from 'components/projects/Dialog/DeleteVariableDialog';
|
||||
import { Input } from 'components/shared/Input';
|
||||
|
||||
const ShowPasswordIcon = ({
|
||||
handler,
|
||||
@ -96,7 +96,7 @@ const EditEnvironmentVariableRow = ({
|
||||
<Input
|
||||
disabled={!edit}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
icon={
|
||||
leftIcon={
|
||||
<ShowPasswordIcon
|
||||
handler={() => {
|
||||
setShowPassword((prevShowPassword) => !prevShowPassword);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { GitSelect } from '../../../../types/types';
|
||||
import { GitSelect } from '../../../../types';
|
||||
|
||||
const GitSelectionSection = ({
|
||||
gitSelectionHandler,
|
||||
|
@ -5,12 +5,12 @@ import {
|
||||
Select,
|
||||
Option,
|
||||
Chip,
|
||||
IconButton,
|
||||
Tooltip,
|
||||
} from '@snowballtools/material-tailwind-react-fork';
|
||||
|
||||
import { formatAddress } from 'utils/format';
|
||||
import { RemoveMemberDialog } from 'components/projects/Dialog/RemoveMemberDialog';
|
||||
import { Tooltip } from 'components/shared/Tooltip';
|
||||
import { Button } from 'components/shared/Button';
|
||||
|
||||
const PERMISSION_OPTIONS = [
|
||||
{
|
||||
@ -125,15 +125,15 @@ const MemberCard = ({
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<IconButton
|
||||
<Button
|
||||
size="sm"
|
||||
className="rounded-full"
|
||||
iconOnly
|
||||
onClick={() => {
|
||||
setRemoveMemberDialogOpen((prevVal) => !prevVal);
|
||||
}}
|
||||
>
|
||||
D
|
||||
</IconButton>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
import { Button } from '@snowballtools/material-tailwind-react-fork';
|
||||
|
||||
import { DeleteWebhookDialog } from 'components/projects/Dialog/DeleteWebhookDialog';
|
||||
import { Button } from 'components/shared/Button';
|
||||
|
||||
interface WebhookCardProps {
|
||||
webhookUrl: string;
|
||||
@ -26,8 +25,8 @@ const WebhookCard = ({ webhookUrl, onDelete }: WebhookCardProps) => {
|
||||
C
|
||||
</Button>
|
||||
<Button
|
||||
color="red"
|
||||
size="sm"
|
||||
variant="danger"
|
||||
onClick={() => {
|
||||
setDeleteDialogOpen(true);
|
||||
}}
|
||||
|
@ -0,0 +1,20 @@
|
||||
import { CustomIcon, CustomIconProps } from './CustomIcon';
|
||||
|
||||
export const ChevronDownSmallIcon = (props: CustomIconProps) => {
|
||||
return (
|
||||
<CustomIcon
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M11.4697 14.5303C11.7626 14.8232 12.2374 14.8232 12.5303 14.5303L16.5303 10.5303C16.8232 10.2374 16.8232 9.76256 16.5303 9.46967C16.2374 9.17678 15.7626 9.17678 15.4697 9.46967L12 12.9393L8.53033 9.46967C8.23744 9.17678 7.76256 9.17678 7.46967 9.46967C7.17678 9.76256 7.17678 10.2374 7.46967 10.5303L11.4697 14.5303Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</CustomIcon>
|
||||
);
|
||||
};
|
@ -0,0 +1,20 @@
|
||||
import { CustomIcon, CustomIconProps } from './CustomIcon';
|
||||
|
||||
export const ChevronUpSmallIcon = (props: CustomIconProps) => {
|
||||
return (
|
||||
<CustomIcon
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M11.4697 9.46967C11.7626 9.17678 12.2374 9.17678 12.5303 9.46967L16.5303 13.4697C16.8232 13.7626 16.8232 14.2374 16.5303 14.5303C16.2374 14.8232 15.7626 14.8232 15.4697 14.5303L12 11.0607L8.53033 14.5303C8.23744 14.8232 7.76256 14.8232 7.46967 14.5303C7.17678 14.2374 7.17678 13.7626 7.46967 13.4697L11.4697 9.46967Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</CustomIcon>
|
||||
);
|
||||
};
|
@ -71,6 +71,8 @@ export * from './TrashIcon';
|
||||
export * from './CopyUnfilledIcon';
|
||||
export * from './SwitchIcon';
|
||||
export * from './CollaboratorsIcon';
|
||||
export * from './ChevronUpSmallIcon';
|
||||
export * from './ChevronDownSmallIcon';
|
||||
|
||||
// Templates
|
||||
export * from './templates';
|
||||
|
@ -4,20 +4,18 @@ import toast from 'react-hot-toast';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Environment, EnvironmentVariable } from 'gql-client';
|
||||
|
||||
import {
|
||||
Collapse,
|
||||
Card,
|
||||
Chip,
|
||||
} from '@snowballtools/material-tailwind-react-fork';
|
||||
import { Collapse } from '@snowballtools/material-tailwind-react-fork';
|
||||
|
||||
import { useGQLClient } from '../../../../../context/GQLClientContext';
|
||||
import { EnvironmentVariablesFormValues } from '../../../../../types';
|
||||
import AddEnvironmentVariableRow from 'components/projects/project/settings/AddEnvironmentVariableRow';
|
||||
import DisplayEnvironmentVariables from 'components/projects/project/settings/DisplayEnvironmentVariables';
|
||||
import { useGQLClient } from '../../../../../context/GQLClientContext';
|
||||
import { EnvironmentVariablesFormValues } from '../../../../../types';
|
||||
import HorizontalLine from 'components/HorizontalLine';
|
||||
import { Heading } from 'components/shared/Heading';
|
||||
import { Button } from 'components/shared/Button';
|
||||
import { Checkbox } from 'components/shared/Checkbox';
|
||||
import { PlusIcon } from 'components/shared/CustomIcon';
|
||||
import { InlineNotification } from 'components/shared/InlineNotification';
|
||||
|
||||
export const EnvironmentVariablesTabPanel = () => {
|
||||
const { id } = useParams();
|
||||
@ -139,15 +137,18 @@ export const EnvironmentVariablesTabPanel = () => {
|
||||
<p className="text-slate-600 text-sm font-normal leading-tight">
|
||||
A new deployment is required for your changes to take effect.
|
||||
</p>
|
||||
<div className="bg-gray-300 rounded-lg p-2">
|
||||
<div
|
||||
className="text-black"
|
||||
<div className="bg-slate-100 rounded-xl flex-col">
|
||||
<Heading
|
||||
onClick={() => setCreateNewVariable((cur) => !cur)}
|
||||
className="p-4"
|
||||
>
|
||||
+ Create new variable
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<PlusIcon />
|
||||
<span>Create new variable</span>
|
||||
</div>
|
||||
</Heading>
|
||||
<Collapse open={createNewVariable}>
|
||||
<Card className="bg-white p-2">
|
||||
<div className="p-4 bg-slate-100">
|
||||
<form onSubmit={handleSubmit(createEnvironmentVariablesHandler)}>
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
@ -162,7 +163,7 @@ export const EnvironmentVariablesTabPanel = () => {
|
||||
})}
|
||||
<div className="flex gap-1 p-2">
|
||||
<Button
|
||||
size="sm"
|
||||
size="md"
|
||||
onClick={() =>
|
||||
append({
|
||||
key: '',
|
||||
@ -173,19 +174,18 @@ export const EnvironmentVariablesTabPanel = () => {
|
||||
+ Add variable
|
||||
</Button>
|
||||
{/* TODO: Implement import environment varible functionality */}
|
||||
<Button size="sm" disabled>
|
||||
<Button size="md" disabled>
|
||||
Import .env
|
||||
</Button>
|
||||
</div>
|
||||
{isFieldEmpty && (
|
||||
<Chip
|
||||
value="^ Please ensure no fields are empty before saving."
|
||||
variant="outlined"
|
||||
color="red"
|
||||
size="sm"
|
||||
<InlineNotification
|
||||
title="Please ensure no fields are empty before saving."
|
||||
variant="danger"
|
||||
size="md"
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
<div className="flex gap-2 p-2">
|
||||
<Checkbox
|
||||
label="Production"
|
||||
{...register(`environment.production`)}
|
||||
@ -208,7 +208,7 @@ export const EnvironmentVariablesTabPanel = () => {
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Card>
|
||||
</div>
|
||||
</Collapse>
|
||||
</div>
|
||||
<div className="p-2">
|
||||
|
@ -0,0 +1,25 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ChevronDownSmallIcon } from 'components/shared/CustomIcon';
|
||||
|
||||
const meta: Meta<typeof ChevronDownSmallIcon> = {
|
||||
title: 'Icons/ChevronDownSmallIcon',
|
||||
component: ChevronDownSmallIcon,
|
||||
tags: ['autodocs'],
|
||||
args: {
|
||||
size: 'string | number' as unknown as any,
|
||||
name: 'string',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof ChevronDownSmallIcon>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: ({ size, name }) => <ChevronDownSmallIcon size={size} name={name} />,
|
||||
args: {
|
||||
size: '24px',
|
||||
name: 'plus',
|
||||
},
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ChevronUpDown } from 'components/shared/CustomIcon/ChevronUpDown';
|
||||
import { ChevronUpDown } from 'components/shared/CustomIcon';
|
||||
|
||||
const meta: Meta<typeof ChevronUpDown> = {
|
||||
title: 'Icons/ChevronUpDown',
|
||||
|
@ -0,0 +1,25 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ChevronUpSmallIcon } from 'components/shared/CustomIcon';
|
||||
|
||||
const meta: Meta<typeof ChevronUpSmallIcon> = {
|
||||
title: 'Components/ChevronUpSmallIcon',
|
||||
component: ChevronUpSmallIcon,
|
||||
tags: ['autodocs'],
|
||||
args: {
|
||||
size: 'string | number' as unknown as any,
|
||||
name: 'string',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof ChevronUpSmallIcon>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: ({ size, name }) => <ChevronUpSmallIcon size={size} name={name} />,
|
||||
args: {
|
||||
size: '24px',
|
||||
name: 'chevron-up',
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user