import { useEffect, useMemo, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { useRouter } from 'next/router'; import { yupResolver } from '@hookform/resolvers/yup'; import NavHeader from '@app/components/navigation/NavHeader'; import { Button, TableContainer, Tooltip } from '@app/components/v2'; import { useWorkspace } from '@app/context'; import { useGetProjectSecretsByKey, useGetUserWsEnvironments, useGetUserWsKey } from '@app/hooks/api'; import { WorkspaceEnv } from '@app/hooks/api/types'; import { EnvComparisonRow } from './components/EnvComparisonRow'; import { FormData, schema } from './DashboardPage.utils'; export const DashboardEnvOverview = ({ onEnvChange }: { onEnvChange: any }) => { const { t } = useTranslation(); const router = useRouter(); const [selectedEnv, setSelectedEnv] = useState(null); const { currentWorkspace, isLoading } = useWorkspace(); const workspaceId = currentWorkspace?._id as string; const { data: latestFileKey } = useGetUserWsKey(workspaceId); useEffect(() => { if (!isLoading && !workspaceId && router.isReady) { router.push('/noprojects'); } }, [isLoading, workspaceId, router.isReady]); const { data: wsEnv, isLoading: isEnvListLoading } = useGetUserWsEnvironments({ workspaceId, onSuccess: (data) => { // get an env with one of the access available const env = data.find(({ isReadDenied }) => !isReadDenied); if (env) { setSelectedEnv(env); } } }); const userAvailableEnvs = wsEnv?.filter(({ isReadDenied }) => !isReadDenied); const { data: secrets, isLoading: isSecretsLoading } = useGetProjectSecretsByKey({ workspaceId, env: userAvailableEnvs?.map((env) => env.slug) ?? [], decryptFileKey: latestFileKey!, isPaused: false }); const method = useForm({ // why any: well yup inferred ts expects other keys to defined as undefined defaultValues: secrets as any, values: secrets as any, mode: 'onBlur', resolver: yupResolver(schema) }); const numSecretsMissingPerEnv = useMemo(() => { // first get all sec in the env then subtract with total to get missing ones const secPerEnvMissing: Record = Object.fromEntries( (userAvailableEnvs || [])?.map(({ slug }) => [slug, 0]) ); Object.keys(secrets?.secrets || {}).forEach((key) => secrets?.secrets?.[key].forEach((val) => { secPerEnvMissing[val.env] += 1; }) ); Object.keys(secPerEnvMissing).forEach((k) => { secPerEnvMissing[k] = (secrets?.uniqueSecCount || 0) - secPerEnvMissing[k]; }); return secPerEnvMissing; }, [secrets, userAvailableEnvs]); const isReadOnly = selectedEnv?.isWriteDenied; if (isSecretsLoading || isEnvListLoading) { return (
loading animation
); } // when secrets is not loading and secrets list is empty const isDashboardSecretEmpty = !isSecretsLoading && !Object.keys(secrets?.secrets || {})?.length; return (
{/* breadcrumb row */}

Secrets Overview

Inject your secrets using Infisical CLI or Infisical SDKs

{0}
Secret
{numSecretsMissingPerEnv && userAvailableEnvs?.map((env) => { return (
{env.name} {numSecretsMissingPerEnv[env.slug] > 0 && (
{numSecretsMissingPerEnv[env.slug]}
)}
); })}
{!isDashboardSecretEmpty && ( {Object.keys(secrets?.secrets || {}).map((key, index) => ( ))}
)} {isDashboardSecretEmpty && (
No secrets are available in this project yet. You can go into any environment to add secrets there.
)} {/* In future, we should add an option to add environments here
*/}
0
0
{userAvailableEnvs?.map((env) => { return (
); })}
); };