Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Copy } from 'lucide-react'
import { useCallback, useState } from 'react'
import { toast } from 'sonner'

import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { Button } from 'ui'
import { getDecryptedValue } from 'data/vault/vault-secret-decrypted-value-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { copyToClipboard } from 'ui'
Expand Down Expand Up @@ -34,29 +34,14 @@ export const CopyEnvButton = ({
).then((values) => values.join('\n'))

copyToClipboard(envFile, () => {
toast.success('Copied to clipboard')
toast.success('Copied to clipboard as .env file')
setIsLoading(false)
})
}, [serverOptions, values])

return (
<ButtonTooltip
type="primary"
loading={isLoading}
icon={<Copy />}
onClick={onCopy}
tooltip={{
content: {
text: (
<span>
Copies an <span className="text-brand">.env file</span> with the configuration details
to your clipboard.
</span>
),
},
}}
>
Copy env values
</ButtonTooltip>
<Button type="default" loading={isLoading} icon={<Copy />} onClick={onCopy}>
Copy all
</Button>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { useState } from 'react'
import { useParams } from 'common'
import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { Button, Input, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { Button, CardContent, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { Input } from 'ui-patterns/DataInputs/Input'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'

export const DecryptedReadOnlyInput = ({
value,
Expand Down Expand Up @@ -41,52 +43,64 @@ export const DecryptedReadOnlyInput = ({
: value

return (
<Input
readOnly
// If the value is secure, allow copying to clipboard if the value is revealed. Otherwise, always allow copying
copy={!secureEntry || (!isDecryptedValueLoading && showHidden)}
disabled
label={
<div className="flex items-center gap-x-2">
<span>{label}</span>
<Tooltip>
<TooltipTrigger asChild>
<a
target="_blank"
rel="noreferrer noopener"
href={`/project/${ref}/integrations/vault/secrets?search=${value}`}
>
<ExternalLink
size={14}
className="text-foreground-lighter hover:text-foreground-light transition"
/>
</a>
</TooltipTrigger>
<TooltipContent side="bottom">View parameter in Vault</TooltipContent>
</Tooltip>
</div>
}
value={renderedValue}
type={secureEntry ? (isLoading ? 'text' : showHidden ? 'text' : 'password') : 'text'}
descriptionText={descriptionText}
layout="horizontal"
actions={
secureEntry ? (
isLoading ? (
<div className="flex items-center justify-center mr-1">
<Button disabled type="default" icon={<Loader className="animate-spin" />} />
</div>
) : (
<div className="flex items-center justify-center mr-1">
<Button
type="default"
icon={showHidden ? <Eye /> : <EyeOff />}
onClick={() => setShowHidden(!showHidden)}
/>
</div>
)
) : null
}
/>
<CardContent className="py-6 border-b border-panel-border-interior-light">
<FormItemLayout
layout="horizontal"
label={
<div className="flex items-center gap-x-2">
<span>{label}</span>
<Tooltip>
<TooltipTrigger asChild>
<a
target="_blank"
rel="noreferrer noopener"
href={`/project/${ref}/integrations/vault/secrets?search=${value}`}
>
<ExternalLink
size={14}
className="text-foreground-muted hover:text-foreground-lighter transition"
/>
</a>
</TooltipTrigger>
<TooltipContent side="bottom">Open in Vault</TooltipContent>
</Tooltip>
</div>
}
description={descriptionText}
isReactForm={false}
>
<Input
readOnly
// If the value is secure, allow copying to clipboard if the value is revealed. Otherwise, always allow copying
copy={!secureEntry || (!isDecryptedValueLoading && showHidden)}
value={renderedValue}
type={secureEntry ? (isLoading ? 'text' : showHidden ? 'text' : 'password') : 'text'}
actions={
secureEntry ? (
isLoading ? (
<div className="flex items-center justify-center">
<Button
disabled
type="default"
className="w-7"
icon={<Loader className="animate-spin" />}
/>
</div>
) : (
<div className="flex items-center justify-center">
<Button
type="default"
className="w-7"
loading={showHidden && isDecryptedValueLoading}
icon={showHidden ? <Eye /> : <EyeOff />}
onClick={() => setShowHidden(!showHidden)}
/>
</div>
)
) : null
}
/>
</FormItemLayout>
</CardContent>
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import Link from '@ui/components/Typography/Link'
import { ScaffoldSectionDescription, ScaffoldSectionTitle } from 'components/layouts/Scaffold'
import {
ScaffoldHeader,
ScaffoldSection,
ScaffoldSectionDescription,
ScaffoldSectionTitle,
} from 'components/layouts/Scaffold'
import { InlineLink } from 'components/ui/InlineLink'
import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { DOCS_URL } from 'lib/constants'
import { Card } from 'ui'
import { getCatalogURI, getConnectionURL } from '../StorageSettings/StorageSettings.utils'
import { DESCRIPTIONS } from './constants'
Expand All @@ -11,9 +17,9 @@ import { DecryptedReadOnlyInput } from './DecryptedReadOnlyInput'

const wrapperMeta = {
options: [
{ name: 'vault_token', label: 'Vault Token', secureEntry: false },
{ name: 'warehouse', label: 'Warehouse', secureEntry: false },
{ name: 's3.endpoint', label: 'S3 Endpoint', secureEntry: false },
{ name: 'vault_token', label: 'Vault token', secureEntry: false },
{ name: 'warehouse', label: 'Warehouse name', secureEntry: false },
{ name: 's3.endpoint', label: 'S3 endpoint', secureEntry: false },
{ name: 'catalog_uri', label: 'Catalog URI', secureEntry: false },
],
}
Expand All @@ -37,24 +43,23 @@ export const SimpleConfigurationDetails = ({ bucketName }: { bucketName: string
}

return (
<div>
<div className="flex flex-row justify-between items-center">
<ScaffoldSection isFullWidth>
<ScaffoldHeader className="flex flex-row justify-between items-end gap-x-8">
<div>
<ScaffoldSectionTitle>Configuration Details</ScaffoldSectionTitle>
<ScaffoldSectionDescription className="mb-4">
You can use the following configuration details to connect to the bucket from your code.
<ScaffoldSectionTitle>Connection details</ScaffoldSectionTitle>
<ScaffoldSectionDescription>
Connect to this bucket from an Iceberg client.{' '}
<InlineLink
href={`${DOCS_URL}/guides/storage/analytics/connecting-to-analytics-bucket`}
>
Learn more
</InlineLink>
</ScaffoldSectionDescription>
</div>
<CopyEnvButton serverOptions={wrapperMeta.options} values={values} />
</div>
<Card className="flex flex-col gap-6 p-6 pb-0">
<p className="text-sm text-foreground-light mb-4">
To get AWS credentials, you can create them using the{' '}
<Link href={`/project/${project?.ref}/storage/settings`}>
<a className="underline ">S3 Access Keys</a>
</Link>{' '}
feature.
</p>
</ScaffoldHeader>

<Card>
{wrapperMeta.options.map((option) => {
return (
<DecryptedReadOnlyInput
Expand All @@ -67,6 +72,6 @@ export const SimpleConfigurationDetails = ({ bucketName }: { bucketName: string
)
})}
</Card>
</div>
</ScaffoldSection>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ export const OPTION_ORDER = [
]

export const LABELS: Record<string, string> = {
vault_aws_access_key_id: 'S3 Access Key ID',
vault_aws_secret_access_key: 'S3 Secret Access Key',
vault_token: 'Catalog Token',
warehouse: 'Warehouse Name',
's3.endpoint': 'S3 Endpoint',
vault_aws_access_key_id: 'S3 access key ID',
vault_aws_secret_access_key: 'S3 secret access key',
vault_token: 'Catalog token',
warehouse: 'Warehouse name',
's3.endpoint': 'S3 endpoint',
catalog_uri: 'Catalog URI',
}

export const DESCRIPTIONS: Record<string, string> = {
vault_aws_access_key_id: 'Matches the AWS access key ID from a S3 Access Key.',
vault_aws_secret_access_key: 'Matches the AWS secret access from a S3 Access Key.',
vault_aws_access_key_id: 'Matches the AWS access key ID from an S3 access key.',
vault_aws_secret_access_key: 'Matches the AWS secret access from an S3 access key.',
vault_token: 'Corresponds to the service role key.',
warehouse: 'Matches the name of the bucket.',
's3.endpoint': '',
Expand Down
Loading
Loading