Merge remote-tracking branch 'origin/main' into feat-secret-input-autocomplete

This commit is contained in:
Sheen Capadngan
2024-04-23 11:02:45 +08:00
939 changed files with 30576 additions and 10095 deletions
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { createNotification } from "@app/components/notifications";
import {
Button,
Checkbox,
@@ -64,7 +64,7 @@ export const CreateSecretForm = ({
const workspaceId = currentWorkspace?.id || "";
const environments = currentWorkspace?.environments || [];
const { createNotification } = useNotificationContext();
const { mutateAsync: createSecretV3 } = useCreateSecretV3();
const { mutateAsync: updateSecretV3 } = useUpdateSecretV3();
@@ -1 +1 @@
export { CreateSecretForm } from "./CreateSecretForm"
export { CreateSecretForm } from "./CreateSecretForm";
@@ -1 +1 @@
export { ProjectIndexSecretsSection } from "./ProjectIndexSecretsSection";
export { ProjectIndexSecretsSection } from "./ProjectIndexSecretsSection";
@@ -0,0 +1,50 @@
import { faCheck, faFingerprint, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { Td, Tr } from "@app/components/v2";
type Props = {
dynamicSecretName: string;
environments: { name: string; slug: string }[];
isDynamicSecretInEnv: (name: string, env: string) => boolean;
};
export const SecretOverviewDynamicSecretRow = ({
dynamicSecretName,
environments = [],
isDynamicSecretInEnv
}: Props) => {
return (
<Tr isHoverable isSelectable className="group">
<Td className="sticky left-0 z-10 border-0 bg-mineshaft-800 bg-clip-padding p-0 group-hover:bg-mineshaft-700">
<div className="flex items-center space-x-5 border-r border-mineshaft-600 px-5 py-2.5">
<div className="text-yellow-700">
<FontAwesomeIcon icon={faFingerprint} />
</div>
<div>{dynamicSecretName}</div>
</div>
</Td>
{environments.map(({ slug }, i) => {
const isPresent = isDynamicSecretInEnv(dynamicSecretName, slug);
return (
<Td
key={`sec-overview-${slug}-${i + 1}-folder`}
className={twMerge(
"border-r border-mineshaft-600 py-3 group-hover:bg-mineshaft-700",
isPresent ? "text-green-600" : "text-red-600"
)}
>
<div className="flex justify-center">
<FontAwesomeIcon
// eslint-disable-next-line no-nested-ternary
icon={isPresent ? faCheck : faXmark}
/>
</div>
</Td>
);
})}
</Tr>
);
};
@@ -0,0 +1 @@
export { SecretOverviewDynamicSecretRow } from "./SecretOverviewDynamicSecretRow";
@@ -15,6 +15,7 @@ export const SecretOverviewFolderRow = ({
folderName,
environments = [],
isFolderPresentInEnv,
onClick
}: Props) => {
return (
@@ -29,6 +30,7 @@ export const SecretOverviewFolderRow = ({
</Td>
{environments.map(({ slug }, i) => {
const isPresent = isFolderPresentInEnv(folderName, slug);
return (
<Td
key={`sec-overview-${slug}-${i + 1}-folder`}
@@ -38,7 +40,10 @@ export const SecretOverviewFolderRow = ({
)}
>
<div className="flex justify-center">
<FontAwesomeIcon icon={isPresent ? faCheck : faXmark} />
<FontAwesomeIcon
// eslint-disable-next-line no-nested-ternary
icon={isPresent ? faCheck : faXmark}
/>
</div>
</Td>
);
@@ -2,8 +2,9 @@ import { Controller, useForm } from "react-hook-form";
import { subject } from "@casl/ability";
import { faCheck, faCopy, faTrash, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions";
import { IconButton, Tooltip } from "@app/components/v2";
import { InfisicalSecretInput } from "@app/components/v2/InfisicalSecretInput/InfisicalSecretInput";
@@ -16,6 +17,7 @@ type Props = {
secretId?: string;
isCreatable?: boolean;
isVisible?: boolean;
isImportedSecret: boolean;
environment: string;
secretPath: string;
onSecretCreate: (env: string, key: string, value: string) => Promise<void>;
@@ -26,6 +28,7 @@ type Props = {
export const SecretEditRow = ({
defaultValue,
isCreatable,
isImportedSecret,
onSecretUpdate,
secretName,
onSecretCreate,
@@ -47,7 +50,6 @@ export const SecretEditRow = ({
}
});
const [isDeleting, setIsDeleting] = useToggle();
const { createNotification } = useNotificationContext();
const handleFormReset = () => {
reset();
@@ -91,6 +93,7 @@ export const SecretEditRow = ({
<div className="group flex w-full cursor-text items-center space-x-2">
<div className="flex-grow border-r border-r-mineshaft-600 pr-2 pl-1">
<Controller
disabled={isImportedSecret}
control={control}
name="value"
render={({ field }) => (
@@ -100,11 +103,17 @@ export const SecretEditRow = ({
isVisible={isVisible}
secretPath={secretPath}
environment={environment}
isImport={isImportedSecret}
/>
)}
/>
</div>
<div className="flex w-16 justify-center space-x-3 pl-2 transition-all">
<div
className={twMerge(
"flex w-16 justify-center space-x-3 pl-2 transition-all",
isImportedSecret && "pointer-events-none opacity-0"
)}
>
{isDirty ? (
<>
<ProjectPermissionCan
@@ -4,6 +4,7 @@ import {
faCheck,
faEye,
faEyeSlash,
faFileImport,
faKey,
faXmark
} from "@fortawesome/free-solid-svg-icons";
@@ -26,6 +27,7 @@ type Props = {
onSecretCreate: (env: string, key: string, value: string) => Promise<void>;
onSecretUpdate: (env: string, key: string, value: string, secretId?: string) => Promise<void>;
onSecretDelete: (env: string, key: string, secretId?: string) => Promise<void>;
isImportedSecretPresentInEnv: (name: string, env: string, secretName: string) => boolean;
};
export const SecretOverviewTableRow = ({
@@ -36,6 +38,7 @@ export const SecretOverviewTableRow = ({
onSecretUpdate,
onSecretCreate,
onSecretDelete,
isImportedSecretPresentInEnv,
expandableColWidth
}: Props) => {
const [isFormExpanded, setIsFormExpanded] = useToggle();
@@ -61,6 +64,9 @@ export const SecretOverviewTableRow = ({
</Td>
{environments.map(({ slug }, i) => {
const secret = getSecretByKey(slug, secretKey);
const isSecretImported = isImportedSecretPresentInEnv(secretPath, slug, secretKey);
const isSecretPresent = Boolean(secret);
const isSecretEmpty = secret?.value === "";
return (
@@ -69,16 +75,29 @@ export const SecretOverviewTableRow = ({
className={twMerge(
"py-0 px-0 group-hover:bg-mineshaft-700",
isFormExpanded && "border-t-2 border-mineshaft-500",
isSecretPresent && !isSecretEmpty ? "text-green-600" : "",
isSecretPresent && isSecretEmpty ? "text-yellow" : "",
!isSecretPresent && !isSecretEmpty ? "text-red-600" : ""
(isSecretPresent && !isSecretEmpty) || isSecretImported ? "text-green-600" : "",
isSecretPresent && isSecretEmpty && !isSecretImported ? "text-yellow" : "",
!isSecretPresent && !isSecretEmpty && !isSecretImported ? "text-red-600" : ""
)}
>
<div className="h-full w-full border-r border-mineshaft-600 py-[0.85rem] px-5">
<div className="flex justify-center">
{!isSecretEmpty && (
<Tooltip content={isSecretPresent ? "Present secret" : "Missing secret"}>
<FontAwesomeIcon icon={isSecretPresent ? faCheck : faXmark} />
<Tooltip
center
content={
// eslint-disable-next-line no-nested-ternary
isSecretPresent
? "Present secret"
: isSecretImported
? "Imported secret"
: "Missing secret"
}
>
<FontAwesomeIcon
// eslint-disable-next-line no-nested-ternary
icon={isSecretPresent ? faCheck : isSecretImported ? faFileImport : faXmark}
/>
</Tooltip>
)}
{isSecretEmpty && (
@@ -143,6 +162,12 @@ export const SecretOverviewTableRow = ({
const secret = getSecretByKey(slug, secretKey);
const isCreatable = !secret;
const isImportedSecret = isImportedSecretPresentInEnv(
secretPath,
slug,
secretKey
);
return (
<tr
key={`secret-expanded-${slug}-${secretKey}`}
@@ -163,6 +188,7 @@ export const SecretOverviewTableRow = ({
secretName={secretKey}
defaultValue={secret?.value}
secretId={secret?.id}
isImportedSecret={isImportedSecret}
isCreatable={isCreatable}
onSecretDelete={onSecretDelete}
onSecretCreate={onSecretCreate}
@@ -8,7 +8,7 @@ import { AnimatePresence, motion } from "framer-motion";
import { twMerge } from "tailwind-merge";
import { z } from "zod";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { createNotification } from "@app/components/notifications";
import { IconButton, Input, Spinner, Tooltip } from "@app/components/v2";
import {
ProjectPermissionActions,
@@ -37,7 +37,7 @@ type TFormSchema = z.infer<typeof formSchema>;
function SecretRenameRow({ environments, getSecretByKey, secretKey, secretPath }: Props) {
const { currentWorkspace } = useWorkspace();
const { permission } = useProjectPermission();
const { createNotification } = useNotificationContext();
const secrets = environments.map((env) => getSecretByKey(env.slug, secretKey));