Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const AppFolderRowBase = ({ appFolder, pathname }: AppFolderRowProps) => {
open ? 'font-bold' : 'font-medium'
)}
>
<FaFolder className="text-emerald-500" />
<FaFolder className="text-amber-500" />
{fullPath}
<FaChevronRight
className={clsx(
Expand Down
48 changes: 46 additions & 2 deletions frontend/app/[team]/apps/[app]/_components/AppSecretRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from 'react-icons/fa'
import { AppSecret } from '../types'
import { organisationContext } from '@/contexts/organisationContext'
import { useContext, useEffect, useMemo, useRef, useState, memo } from 'react'
import { useCallback, useContext, useEffect, useMemo, useRef, useState, memo } from 'react'
import { Button } from '@/components/common/Button'
import { useMutation } from '@apollo/client'
import Link from 'next/link'
Expand All @@ -24,6 +24,9 @@ import { arraysEqual } from '@/utils/crypto'
import { toggleBooleanKeepingCase } from '@/utils/secrets'
import CopyButton from '@/components/common/CopyButton'
import { MaskedTextarea } from '@/components/common/MaskedTextarea'
import { useSecretReferenceAutocomplete } from '@/hooks/useSecretReferenceAutocomplete'
import { ReferenceAutocompleteDropdown } from '@/components/secrets/ReferenceAutocompleteDropdown'
import { SecretReferenceHighlight } from '@/components/secrets/SecretReferenceHighlight'
import {
PresentIndicator,
SameAsProdIndicator,
Expand Down Expand Up @@ -53,6 +56,7 @@ const EnvSecretComponent = ({
updateEnvValue,
addEnvValue,
deleteEnvValue,
currentSecretKey,
revealOnHover,
}: {
clientEnvSecret: {
Expand All @@ -69,6 +73,7 @@ const EnvSecretComponent = ({
updateEnvValue: (id: string, envId: string, value: string | undefined) => void
addEnvValue: (appSecretId: string, environment: EnvironmentType) => void
deleteEnvValue: (appSecretId: string, environment: EnvironmentType) => void
currentSecretKey?: string
revealOnHover?: boolean
}) => {
const pathname = usePathname()
Expand All @@ -82,6 +87,27 @@ const EnvSecretComponent = ({
valueIsNew || !serverEnvSecret || isEmptyValue || false
)

// Secret reference autocomplete
const textareaRef = useRef<HTMLTextAreaElement>(null)
const handleValueChange = useCallback(
(v: string) => updateEnvValue(appSecretId, clientEnvSecret.env.id!, v),
[updateEnvValue, appSecretId, clientEnvSecret.env.id]
)

const autocomplete = useSecretReferenceAutocomplete({
value: clientEnvSecret.secret?.value ?? '',
isRevealed: showValue,
textareaRef,
onChange: handleValueChange,
currentSecretKey,
})

const secretValue = clientEnvSecret.secret?.value ?? ''
const highlightContent =
showValue && secretValue.includes('${') ? (
<SecretReferenceHighlight value={secretValue} />
) : undefined

const isBoolean = clientEnvSecret?.secret
? ['true', 'false'].includes(clientEnvSecret.secret.value.toLowerCase())
: false
Expand Down Expand Up @@ -231,17 +257,33 @@ const EnvSecretComponent = ({
</div>
)}
<MaskedTextarea
ref={textareaRef}
className={clsx(
INPUT_BASE_STYLE,
inputTextColor(),
'rounded-sm focus:outline-none py-2 pl-2'
)}
value={clientEnvSecret.secret.value}
onChange={(v) => updateEnvValue(appSecretId, clientEnvSecret.env.id!, v)}
onChange={(v) => {
handleValueChange(v)
autocomplete.handleChange()
}}
onKeyDown={autocomplete.handleKeyDown}
onSelect={autocomplete.handleSelect}
onBlur={autocomplete.handleBlur}
onFocus={autocomplete.handleFocus}
isRevealed={showValue}
expanded={true}
highlightContent={highlightContent}
/>
</div>
<ReferenceAutocompleteDropdown
suggestions={autocomplete.suggestions}
activeIndex={autocomplete.activeIndex}
onSelect={autocomplete.acceptSuggestion}
onNavigate={autocomplete.navigateToSuggestion}
visible={autocomplete.isOpen}
/>
{clientEnvSecret.secret !== null && (
<div className="flex items-center gap-2 absolute inset-y-0 right-0 pl-32 pr-2 opacity-0 group-hover:opacity-100 transition ease bg-gradient-to-r from-transparent via-zinc-100/90 to-zinc-100 dark:via-zinc-800/90 dark:to-zinc-800 group-hover:via-zinc-200/90 group-hover:to-zinc-200 dark:group-hover:via-zinc-700/90 dark:group-hover:to-zinc-700">
<Button variant="outline" onClick={toggleShowValue}>
Expand Down Expand Up @@ -273,6 +315,7 @@ const areEnvSecretEqual = (
prev.appSecretId === next.appSecretId &&
prev.keyIsStagedForDelete === next.keyIsStagedForDelete &&
prev.sameAsProd === next.sameAsProd &&
prev.currentSecretKey === next.currentSecretKey &&
prev.revealOnHover === next.revealOnHover &&
prev.clientEnvSecret.env.id === next.clientEnvSecret.env.id &&
(p?.id ?? null) === (n?.id ?? null) &&
Expand Down Expand Up @@ -567,6 +610,7 @@ const AppSecretRowComponent = ({
updateEnvValue={updateValue}
addEnvValue={addEnvValue}
deleteEnvValue={deleteEnvValue}
currentSecretKey={clientAppSecret.key}
revealOnHover={revealOnHover}
/>
))}
Expand Down
Loading