mirror of
https://github.com/langgenius/dify.git
synced 2026-05-09 12:59:18 +08:00
tweaks
This commit is contained in:
parent
b70c9d7835
commit
23ffbd2532
@ -1,12 +1,10 @@
|
||||
import AccessTab from '@/features/deployments/detail/access-tab'
|
||||
import { AccessTab } from '@/features/deployments/detail/access-tab'
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailAccessPage = async ({ params }: PageProps) => {
|
||||
export default async function InstanceDetailAccessPage({ params }: PageProps) {
|
||||
const { instanceId } = await params
|
||||
return <AccessTab instanceId={instanceId} />
|
||||
}
|
||||
|
||||
export default InstanceDetailAccessPage
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import DeployTab from '@/features/deployments/detail/deploy-tab'
|
||||
import { DeployTab } from '@/features/deployments/detail/deploy-tab'
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailDeployPage = async ({ params }: PageProps) => {
|
||||
export default async function InstanceDetailDeployPage({ params }: PageProps) {
|
||||
const { instanceId } = await params
|
||||
return <DeployTab instanceId={instanceId} />
|
||||
}
|
||||
|
||||
export default InstanceDetailDeployPage
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import InstanceDetail from '@/features/deployments/detail'
|
||||
import { InstanceDetail } from '@/features/deployments/detail'
|
||||
|
||||
type LayoutProps = {
|
||||
children: ReactNode
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailLayout = async ({ children, params }: LayoutProps) => {
|
||||
export default async function InstanceDetailLayout({ children, params }: LayoutProps) {
|
||||
const { instanceId } = await params
|
||||
|
||||
return (
|
||||
@ -15,5 +15,3 @@ const InstanceDetailLayout = async ({ children, params }: LayoutProps) => {
|
||||
</InstanceDetail>
|
||||
)
|
||||
}
|
||||
|
||||
export default InstanceDetailLayout
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import OverviewTab from '@/features/deployments/detail/overview-tab'
|
||||
import { OverviewTab } from '@/features/deployments/detail/overview-tab'
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailOverviewPage = async ({ params }: PageProps) => {
|
||||
export default async function InstanceDetailOverviewPage({ params }: PageProps) {
|
||||
const { instanceId } = await params
|
||||
return <OverviewTab instanceId={instanceId} />
|
||||
}
|
||||
|
||||
export default InstanceDetailOverviewPage
|
||||
|
||||
@ -4,9 +4,7 @@ type PageProps = {
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailPage = async ({ params }: PageProps) => {
|
||||
export default async function InstanceDetailPage({ params }: PageProps) {
|
||||
const { instanceId } = await params
|
||||
redirect(`/deployments/${instanceId}/overview`)
|
||||
}
|
||||
|
||||
export default InstanceDetailPage
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import SettingsTab from '@/features/deployments/detail/settings-tab'
|
||||
import { SettingsTab } from '@/features/deployments/detail/settings-tab'
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailSettingsPage = async ({ params }: PageProps) => {
|
||||
export default async function InstanceDetailSettingsPage({ params }: PageProps) {
|
||||
const { instanceId } = await params
|
||||
return <SettingsTab instanceId={instanceId} />
|
||||
}
|
||||
|
||||
export default InstanceDetailSettingsPage
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import VersionsTab from '@/features/deployments/detail/versions-tab'
|
||||
import { VersionsTab } from '@/features/deployments/detail/versions-tab'
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ instanceId: string }>
|
||||
}
|
||||
|
||||
const InstanceDetailVersionsPage = async ({ params }: PageProps) => {
|
||||
export default async function InstanceDetailVersionsPage({ params }: PageProps) {
|
||||
const { instanceId } = await params
|
||||
return <VersionsTab instanceId={instanceId} />
|
||||
}
|
||||
|
||||
export default InstanceDetailVersionsPage
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import DeploymentsMain from '@/features/deployments/list'
|
||||
import { DeploymentsMain } from '@/features/deployments/list'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
|
||||
const DeploymentsPage = () => {
|
||||
export default function DeploymentsPage() {
|
||||
const { t } = useTranslation('deployments')
|
||||
useDocumentTitle(t('documentTitle.list'))
|
||||
return <DeploymentsMain />
|
||||
}
|
||||
|
||||
export default DeploymentsPage
|
||||
|
||||
@ -9,7 +9,7 @@ type UseWorkflowOnlineUsersParams = {
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
const normalizeWorkflowOnlineUsers = (response?: WorkflowOnlineUsersResponse): WorkflowOnlineUsersMap => {
|
||||
function normalizeWorkflowOnlineUsers(response?: WorkflowOnlineUsersResponse): WorkflowOnlineUsersMap {
|
||||
const data = response?.data
|
||||
|
||||
if (!data)
|
||||
@ -30,10 +30,10 @@ const normalizeWorkflowOnlineUsers = (response?: WorkflowOnlineUsersResponse): W
|
||||
}, {})
|
||||
}
|
||||
|
||||
export const useWorkflowOnlineUsers = ({
|
||||
export function useWorkflowOnlineUsers({
|
||||
appIds,
|
||||
enabled,
|
||||
}: UseWorkflowOnlineUsersParams) => {
|
||||
}: UseWorkflowOnlineUsersParams) {
|
||||
const shouldFetch = enabled && appIds.length > 0
|
||||
const { data: onlineUsersMap = {} } = useQuery(consoleQuery.apps.workflowOnlineUsers.queryOptions({
|
||||
input: {
|
||||
|
||||
@ -8,7 +8,7 @@ import { useAppContext } from '@/context/app-context'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { WorkspaceProvider } from '@/context/workspace-context-provider'
|
||||
import DeploymentsNav from '@/features/deployments/nav'
|
||||
import { DeploymentsNav } from '@/features/deployments/nav'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { AppInfo, AppMode } from '../types'
|
||||
import type { App, AppModeEnum } from '@/types/app'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
@ -39,7 +38,7 @@ type AppPickerProps = {
|
||||
onChange: (appId: string) => void
|
||||
}
|
||||
|
||||
export const AppPicker: FC<AppPickerProps> = ({ apps, isLoading, value, onChange }) => {
|
||||
export function AppPicker({ apps, isLoading, value, onChange }: AppPickerProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const [open, setOpen] = useState(false)
|
||||
const [keywords, setKeywords] = useState('')
|
||||
@ -204,7 +203,11 @@ export const AppPicker: FC<AppPickerProps> = ({ apps, isLoading, value, onChange
|
||||
)
|
||||
}
|
||||
|
||||
const CreateInstanceForm: FC<{ onClose: () => void }> = ({ onClose }) => {
|
||||
type CreateInstanceFormProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
function CreateInstanceForm({ onClose }: CreateInstanceFormProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const router = useRouter()
|
||||
const createInstance = useMutation(consoleQuery.enterprise.appDeploy.createAppInstance.mutationOptions())
|
||||
@ -310,7 +313,7 @@ const CreateInstanceForm: FC<{ onClose: () => void }> = ({ onClose }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const CreateInstanceModal: FC = () => {
|
||||
export function CreateInstanceModal() {
|
||||
const modal = useDeploymentsStore(state => state.createInstanceModal)
|
||||
const closeModal = useDeploymentsStore(state => state.closeCreateInstanceModal)
|
||||
|
||||
@ -326,5 +329,3 @@ const CreateInstanceModal: FC = () => {
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateInstanceModal
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { Dialog, DialogCloseButton, DialogContent } from '@langgenius/dify-ui/dialog'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { skipToken, useMutation, useQuery } from '@tanstack/react-query'
|
||||
@ -12,7 +11,7 @@ import { useDeploymentsStore } from '../store'
|
||||
import { environmentOptionsFromOptionsReply } from '../utils'
|
||||
import { DeployForm } from './deploy-drawer/form'
|
||||
|
||||
const DeployDrawer: FC = () => {
|
||||
export function DeployDrawer() {
|
||||
const { t } = useTranslation('deployments')
|
||||
const drawer = useDeploymentsStore(state => state.deployDrawer)
|
||||
const drawerAppInstanceId = drawer.appInstanceId
|
||||
@ -95,5 +94,3 @@ const DeployDrawer: FC = () => {
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default DeployDrawer
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { DeploymentBindingOptionSlot, DeploymentRuntimeBinding } from '@dify/contracts/enterprise/types.gen'
|
||||
import type { FC } from 'react'
|
||||
import type { ConsoleReleaseSummary, EnvironmentOption } from '@/features/deployments/types'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { DialogDescription, DialogTitle } from '@langgenius/dify-ui/dialog'
|
||||
@ -54,12 +53,15 @@ type BindingOptionsPanelProps = {
|
||||
onChange: (slot: string, value: string) => void
|
||||
}
|
||||
|
||||
const isEnvBindingSlot = (slot: DeploymentBindingOptionSlot) =>
|
||||
(slot.kind?.toLowerCase() ?? '').includes('env')
|
||||
function isEnvBindingSlot(slot: DeploymentBindingOptionSlot) {
|
||||
return (slot.kind?.toLowerCase() ?? '').includes('env')
|
||||
}
|
||||
|
||||
const bindingSlotKey = (slot: DeploymentBindingOptionSlot) => slot.slot ?? ''
|
||||
function bindingSlotKey(slot: DeploymentBindingOptionSlot) {
|
||||
return slot.slot ?? ''
|
||||
}
|
||||
|
||||
const bindingCandidateOptions = (slot: DeploymentBindingOptionSlot): BindingSelectOption[] => {
|
||||
function bindingCandidateOptions(slot: DeploymentBindingOptionSlot): BindingSelectOption[] {
|
||||
if (isEnvBindingSlot(slot)) {
|
||||
return (slot.envVarCandidates ?? [])
|
||||
.filter(candidate => candidate.envVarId)
|
||||
@ -84,13 +86,11 @@ const bindingCandidateOptions = (slot: DeploymentBindingOptionSlot): BindingSele
|
||||
}))
|
||||
}
|
||||
|
||||
const hasMissingRequiredBinding = (slot: DeploymentBindingOptionSlot, selectedValue?: string) =>
|
||||
Boolean(slot.required && !selectedValue)
|
||||
function hasMissingRequiredBinding(slot: DeploymentBindingOptionSlot, selectedValue?: string) {
|
||||
return Boolean(slot.required && !selectedValue)
|
||||
}
|
||||
|
||||
const selectedDeploymentBindings = (
|
||||
slots: DeploymentBindingOptionSlot[],
|
||||
selections: BindingSelections,
|
||||
): DeploymentRuntimeBinding[] => {
|
||||
function selectedDeploymentBindings(slots: DeploymentBindingOptionSlot[], selections: BindingSelections): DeploymentRuntimeBinding[] {
|
||||
return slots
|
||||
.map((slot): DeploymentRuntimeBinding | undefined => {
|
||||
const slotKey = bindingSlotKey(slot)
|
||||
@ -105,13 +105,13 @@ const selectedDeploymentBindings = (
|
||||
.filter((binding): binding is DeploymentRuntimeBinding => Boolean(binding))
|
||||
}
|
||||
|
||||
const BindingOptionsPanel: FC<BindingOptionsPanelProps> = ({
|
||||
function BindingOptionsPanel({
|
||||
slots,
|
||||
selections,
|
||||
isLoading,
|
||||
hasError,
|
||||
onChange,
|
||||
}) => {
|
||||
}: BindingOptionsPanelProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
|
||||
if (isLoading) {
|
||||
@ -192,7 +192,7 @@ const BindingOptionsPanel: FC<BindingOptionsPanelProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export const DeployForm: FC<DeployFormProps> = ({
|
||||
export function DeployForm({
|
||||
appInstanceId,
|
||||
environments,
|
||||
releases,
|
||||
@ -202,7 +202,7 @@ export const DeployForm: FC<DeployFormProps> = ({
|
||||
isSubmitting,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
}) => {
|
||||
}: DeployFormProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const presetRelease = useMemo(
|
||||
() => presetReleaseId ? releases.find(r => r.id === presetReleaseId) : undefined,
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { EnvironmentOption } from '@/features/deployments/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select'
|
||||
@ -14,15 +13,17 @@ type FieldProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const Field: FC<FieldProps> = ({ label, hint, children }) => (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="system-xs-medium-uppercase text-text-tertiary">{label}</div>
|
||||
{hint && <span className="system-xs-regular text-text-quaternary">{hint}</span>}
|
||||
export function Field({ label, hint, children }: FieldProps) {
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="system-xs-medium-uppercase text-text-tertiary">{label}</div>
|
||||
{hint && <span className="system-xs-regular text-text-quaternary">{hint}</span>}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
type SelectOption = {
|
||||
value: string
|
||||
@ -38,7 +39,7 @@ type SelectProps = {
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
export const DeploymentSelect: FC<SelectProps> = ({ value, onChange, options, placeholder }) => {
|
||||
export function DeploymentSelect({ value, onChange, options, placeholder }: SelectProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const selectedOption = options.find(option => option.value === value)
|
||||
|
||||
@ -79,13 +80,15 @@ export const DeploymentSelect: FC<SelectProps> = ({ value, onChange, options, pl
|
||||
|
||||
type EnvironmentRowProps = { env: EnvironmentOption }
|
||||
|
||||
export const EnvironmentRow: FC<EnvironmentRowProps> = ({ env }) => (
|
||||
<div className="flex items-center justify-between rounded-lg border border-components-panel-border bg-components-panel-bg-blur px-3 py-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="system-sm-semibold text-text-primary">{environmentName(env)}</span>
|
||||
<ModeBadge mode={environmentMode(env)} />
|
||||
<HealthBadge health={environmentHealth(env)} />
|
||||
export function EnvironmentRow({ env }: EnvironmentRowProps) {
|
||||
return (
|
||||
<div className="flex items-center justify-between rounded-lg border border-components-panel-border bg-components-panel-bg-blur px-3 py-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="system-sm-semibold text-text-primary">{environmentName(env)}</span>
|
||||
<ModeBadge mode={environmentMode(env)} />
|
||||
<HealthBadge health={environmentHealth(env)} />
|
||||
</div>
|
||||
<span className="system-xs-regular text-text-tertiary uppercase">{env.type ?? 'env'}</span>
|
||||
</div>
|
||||
<span className="system-xs-regular text-text-tertiary uppercase">{env.type ?? 'env'}</span>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogActions,
|
||||
@ -26,7 +25,12 @@ import {
|
||||
toAppInfoFromOverview,
|
||||
} from '../utils'
|
||||
|
||||
const InfoRow: FC<{ label: string, value: string }> = ({ label, value }) => {
|
||||
type InfoRowProps = {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
function InfoRow({ label, value }: InfoRowProps) {
|
||||
return (
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<span className="system-xs-medium-uppercase text-text-tertiary">{label}</span>
|
||||
@ -35,7 +39,7 @@ const InfoRow: FC<{ label: string, value: string }> = ({ label, value }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const RollbackModal: FC = () => {
|
||||
export function RollbackModal() {
|
||||
const { t } = useTranslation('deployments')
|
||||
const modal = useDeploymentsStore(state => state.rollbackModal)
|
||||
const closeRollbackModal = useDeploymentsStore(state => state.closeRollbackModal)
|
||||
@ -146,5 +150,3 @@ const RollbackModal: FC = () => {
|
||||
</AlertDialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default RollbackModal
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { DeployStatus, EnvironmentHealth, EnvironmentMode } from '../types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -23,7 +22,7 @@ const statusKey = {
|
||||
|
||||
const baseBadge = 'inline-flex items-center gap-1 rounded-md border px-2 py-0.5 system-xs-medium whitespace-nowrap'
|
||||
|
||||
export const StatusBadge: FC<StatusBadgeProps> = ({ status, className }) => {
|
||||
export function StatusBadge({ status, className }: StatusBadgeProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
return (
|
||||
<span className={cn(baseBadge, statusStyles[status], className)}>
|
||||
@ -40,7 +39,7 @@ type ModeBadgeProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const ModeBadge: FC<ModeBadgeProps> = ({ mode, className }) => {
|
||||
export function ModeBadge({ mode, className }: ModeBadgeProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const style = mode === 'shared'
|
||||
? 'border-util-colors-green-green-200 bg-util-colors-green-green-50 text-util-colors-green-green-700'
|
||||
@ -57,7 +56,7 @@ type HealthBadgeProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const HealthBadge: FC<HealthBadgeProps> = ({ health, className }) => {
|
||||
export function HealthBadge({ health, className }: HealthBadgeProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const style = health === 'ready'
|
||||
? 'border-util-colors-green-green-200 bg-util-colors-green-green-50 text-util-colors-green-green-700'
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type {
|
||||
AccessPermission,
|
||||
AccessSubject,
|
||||
@ -31,7 +30,7 @@ type AccessTabProps = {
|
||||
instanceId: string
|
||||
}
|
||||
|
||||
const AccessTab: FC<AccessTabProps> = ({ instanceId: appId }) => {
|
||||
export function AccessTab({ instanceId: appId }: AccessTabProps) {
|
||||
const appInput = { params: { appInstanceId: appId } }
|
||||
const { data: accessConfig } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceAccess.queryOptions({
|
||||
input: appInput,
|
||||
@ -171,5 +170,3 @@ const AccessTab: FC<AccessTabProps> = ({ instanceId: appId }) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccessTab
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { ConsoleEnvironmentSummary, DeveloperAPIKeySummary } from '@/features/deployments/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import {
|
||||
@ -20,7 +19,7 @@ type ApiKeyRowProps = {
|
||||
onRevoke: () => void
|
||||
}
|
||||
|
||||
export const ApiKeyRow: FC<ApiKeyRowProps> = ({ apiKey, onCopy, onRevoke }) => {
|
||||
export function ApiKeyRow({ apiKey, onCopy, onRevoke }: ApiKeyRowProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const [copied, setCopied] = useState(false)
|
||||
const displayValue = apiKey.maskedKey || apiKey.maskedPrefix || apiKey.id || '—'
|
||||
@ -80,7 +79,7 @@ type ApiKeyGenerateMenuProps = {
|
||||
onGenerate: (environmentId: string) => void
|
||||
}
|
||||
|
||||
export const ApiKeyGenerateMenu: FC<ApiKeyGenerateMenuProps> = ({ environments, onGenerate }) => {
|
||||
export function ApiKeyGenerateMenu({ environments, onGenerate }: ApiKeyGenerateMenuProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const [open, setOpen] = useState(false)
|
||||
const selectableEnvironments = environments.filter(env => env.id)
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { WebAppAccessRow } from '@/features/deployments/types'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -15,13 +14,13 @@ type AccessChannelsSectionProps = {
|
||||
onToggle: (enabled: boolean) => void
|
||||
}
|
||||
|
||||
export const AccessChannelsSection: FC<AccessChannelsSectionProps> = ({
|
||||
export function AccessChannelsSection({
|
||||
runEnabled,
|
||||
webappRows,
|
||||
cliDomain,
|
||||
cliDocsUrl,
|
||||
onToggle,
|
||||
}) => {
|
||||
}: AccessChannelsSectionProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
|
||||
return (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { useState } from 'react'
|
||||
@ -13,20 +13,22 @@ type SectionProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const Section: FC<SectionProps> = ({ title, description, action, children }) => (
|
||||
<div className="flex flex-col gap-3 rounded-xl border border-components-panel-border bg-components-panel-bg p-4">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div className="system-sm-semibold text-text-primary">{title}</div>
|
||||
{description && (
|
||||
<p className="mt-1 max-w-xl system-xs-regular text-text-tertiary">{description}</p>
|
||||
)}
|
||||
export function Section({ title, description, action, children }: SectionProps) {
|
||||
return (
|
||||
<div className="flex flex-col gap-3 rounded-xl border border-components-panel-border bg-components-panel-bg p-4">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div className="system-sm-semibold text-text-primary">{title}</div>
|
||||
{description && (
|
||||
<p className="mt-1 max-w-xl system-xs-regular text-text-tertiary">{description}</p>
|
||||
)}
|
||||
</div>
|
||||
{action}
|
||||
</div>
|
||||
{action}
|
||||
{children}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
type CopyPillProps = {
|
||||
label: string
|
||||
@ -35,7 +37,7 @@ type CopyPillProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const CopyPill: FC<CopyPillProps> = ({ label, value, prefix, className }) => {
|
||||
export function CopyPill({ label, value, prefix, className }: CopyPillProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
@ -85,22 +87,24 @@ type EndpointRowProps = {
|
||||
openLabel?: string
|
||||
}
|
||||
|
||||
export const EndpointRow: FC<EndpointRowProps> = ({ envName, label, value, openLabel }) => (
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1.5">
|
||||
<span className="min-w-[140px] system-xs-regular text-text-tertiary">
|
||||
{envName}
|
||||
</span>
|
||||
<CopyPill label={label} value={value} className="min-w-[260px] flex-1" />
|
||||
{openLabel && (
|
||||
<a
|
||||
href={value}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-components-button-secondary-border bg-components-button-secondary-bg px-3 system-sm-medium text-components-button-secondary-text hover:bg-components-button-secondary-bg-hover"
|
||||
>
|
||||
<span className="i-ri-external-link-line h-3.5 w-3.5" />
|
||||
{openLabel}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
export function EndpointRow({ envName, label, value, openLabel }: EndpointRowProps) {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1.5">
|
||||
<span className="min-w-[140px] system-xs-regular text-text-tertiary">
|
||||
{envName}
|
||||
</span>
|
||||
<CopyPill label={label} value={value} className="min-w-[260px] flex-1" />
|
||||
{openLabel && (
|
||||
<a
|
||||
href={value}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-components-button-secondary-border bg-components-button-secondary-bg px-3 system-sm-medium text-components-button-secondary-text hover:bg-components-button-secondary-bg-hover"
|
||||
>
|
||||
<span className="i-ri-external-link-line h-3.5 w-3.5" />
|
||||
{openLabel}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { ConsoleEnvironmentSummary, DeveloperAPIKeySummary } from '@/features/deployments/types'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -20,7 +19,7 @@ type DeveloperApiSectionProps = {
|
||||
onClearCreatedToken: () => void
|
||||
}
|
||||
|
||||
export const DeveloperApiSection: FC<DeveloperApiSectionProps> = ({
|
||||
export function DeveloperApiSection({
|
||||
apiEnabled,
|
||||
apiUrl,
|
||||
environments,
|
||||
@ -31,7 +30,7 @@ export const DeveloperApiSection: FC<DeveloperApiSectionProps> = ({
|
||||
onCopyApiKey,
|
||||
onRevoke,
|
||||
onClearCreatedToken,
|
||||
}) => {
|
||||
}: DeveloperApiSectionProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
|
||||
return (
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { AccessPermission, AccessSubject, ConsoleEnvironmentSummary } from '@/features/deployments/types'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Section } from './common'
|
||||
@ -18,12 +17,12 @@ type AccessPermissionsSectionProps = {
|
||||
) => Promise<void>
|
||||
}
|
||||
|
||||
export const AccessPermissionsSection: FC<AccessPermissionsSectionProps> = ({
|
||||
export function AccessPermissionsSection({
|
||||
appId,
|
||||
environments,
|
||||
policies,
|
||||
onSetPolicy,
|
||||
}) => {
|
||||
}: AccessPermissionsSectionProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
|
||||
return (
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { AccessPermissionKind } from '../../types'
|
||||
import type {
|
||||
AccessPermission,
|
||||
@ -43,7 +42,7 @@ type PermissionPickerProps = {
|
||||
onChange: (kind: AccessPermissionKind) => void
|
||||
}
|
||||
|
||||
const PermissionPicker: FC<PermissionPickerProps> = ({ value, disabled, onChange }) => {
|
||||
function PermissionPicker({ value, disabled, onChange }: PermissionPickerProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const icon = permissionIcon[value]
|
||||
const label = t(`access.permission.${value}`)
|
||||
@ -142,7 +141,7 @@ type SubjectPillProps = {
|
||||
onRemove: () => void
|
||||
}
|
||||
|
||||
const SubjectPill: FC<SubjectPillProps> = ({ subject, disabled, onRemove }) => {
|
||||
function SubjectPill({ subject, disabled, onRemove }: SubjectPillProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const isGroup = subject.subjectType === 'group'
|
||||
|
||||
@ -176,12 +175,12 @@ type SubjectPickerProps = {
|
||||
onChange: (subjects: SelectableAccessSubject[]) => void
|
||||
}
|
||||
|
||||
const SubjectPicker: FC<SubjectPickerProps> = ({
|
||||
function SubjectPicker({
|
||||
appId,
|
||||
disabled,
|
||||
selectedSubjects,
|
||||
onChange,
|
||||
}) => {
|
||||
}: SubjectPickerProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const [open, setOpen] = useState(false)
|
||||
const [keyword, setKeyword] = useState('')
|
||||
@ -308,12 +307,12 @@ type EnvironmentPermissionRowProps = {
|
||||
) => Promise<void>
|
||||
}
|
||||
|
||||
export const EnvironmentPermissionRow: FC<EnvironmentPermissionRowProps> = ({
|
||||
export function EnvironmentPermissionRow({
|
||||
appId,
|
||||
environment,
|
||||
summaryPolicy,
|
||||
onSetPolicy,
|
||||
}) => {
|
||||
}: EnvironmentPermissionRowProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const environmentId = environment.id
|
||||
const policyQuery = useQuery(consoleQuery.enterprise.appDeploy.getEnvironmentAccessPolicy.queryOptions({
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { FC, KeyboardEvent } from 'react'
|
||||
import type { KeyboardEvent } from 'react'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import {
|
||||
@ -36,7 +36,7 @@ type DeployTabProps = {
|
||||
instanceId: string
|
||||
}
|
||||
|
||||
const DeployTab: FC<DeployTabProps> = ({ instanceId: appInstanceId }) => {
|
||||
export function DeployTab({ instanceId: appInstanceId }: DeployTabProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({
|
||||
input: {
|
||||
@ -302,5 +302,3 @@ const DeployTab: FC<DeployTabProps> = ({ instanceId: appInstanceId }) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DeployTab
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { EnvironmentDeploymentRow, RuntimeBindingDisplay } from '@/features/deployments/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -23,12 +23,14 @@ type InfoBlockProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const InfoBlock: FC<InfoBlockProps> = ({ title, children }) => (
|
||||
<div className="min-w-0 rounded-lg bg-background-default px-3 py-2.5">
|
||||
<div className="mb-2 system-xs-medium-uppercase text-text-tertiary">{title}</div>
|
||||
<div className="flex flex-col gap-1.5">{children}</div>
|
||||
</div>
|
||||
)
|
||||
function InfoBlock({ title, children }: InfoBlockProps) {
|
||||
return (
|
||||
<div className="min-w-0 rounded-lg bg-background-default px-3 py-2.5">
|
||||
<div className="mb-2 system-xs-medium-uppercase text-text-tertiary">{title}</div>
|
||||
<div className="flex flex-col gap-1.5">{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type InfoRowProps = {
|
||||
label: string
|
||||
@ -37,21 +39,23 @@ type InfoRowProps = {
|
||||
suffix?: string
|
||||
}
|
||||
|
||||
const InfoRow: FC<InfoRowProps> = ({ label, value, mono, suffix }) => (
|
||||
<div className="grid min-w-0 grid-cols-[minmax(88px,0.35fr)_minmax(0,1fr)] items-start gap-2">
|
||||
<span className="system-xs-regular text-text-tertiary">{label}</span>
|
||||
<span className={cn('min-w-0 system-sm-regular break-all text-text-primary', mono && 'font-mono')}>
|
||||
{value}
|
||||
{suffix && <span className="system-xs-regular text-text-tertiary">{suffix}</span>}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
function InfoRow({ label, value, mono, suffix }: InfoRowProps) {
|
||||
return (
|
||||
<div className="grid min-w-0 grid-cols-[minmax(88px,0.35fr)_minmax(0,1fr)] items-start gap-2">
|
||||
<span className="system-xs-regular text-text-tertiary">{label}</span>
|
||||
<span className={cn('min-w-0 system-sm-regular break-all text-text-primary', mono && 'font-mono')}>
|
||||
{value}
|
||||
{suffix && <span className="system-xs-regular text-text-tertiary">{suffix}</span>}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type RuntimeBindingItemProps = {
|
||||
binding: RuntimeBindingDisplay
|
||||
}
|
||||
|
||||
const RuntimeBindingItem: FC<RuntimeBindingItemProps> = ({ binding }) => {
|
||||
function RuntimeBindingItem({ binding }: RuntimeBindingItemProps) {
|
||||
const summary = runtimeBindingSummary(binding)
|
||||
|
||||
return (
|
||||
@ -67,7 +71,7 @@ type DeploymentPanelProps = {
|
||||
row: EnvironmentDeploymentRow
|
||||
}
|
||||
|
||||
export const DeploymentPanel: FC<DeploymentPanelProps> = ({ row }) => {
|
||||
export function DeploymentPanel({ row }: DeploymentPanelProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const observed = activeRelease(row)
|
||||
const env = row.environment
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { EnvironmentDeploymentRow } from '@/features/deployments/types'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
@ -14,7 +13,7 @@ type DeploymentStatusSummaryProps = {
|
||||
row: EnvironmentDeploymentRow
|
||||
}
|
||||
|
||||
export const DeploymentStatusSummary: FC<DeploymentStatusSummaryProps> = ({ row }) => {
|
||||
export function DeploymentStatusSummary({ row }: DeploymentStatusSummaryProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
if (isUndeployedDeploymentRow(row)) {
|
||||
return (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { ComponentProps, FC, PropsWithoutRef } from 'react'
|
||||
import type { ComponentProps, PropsWithoutRef } from 'react'
|
||||
import type { AppInfo } from '../types'
|
||||
import type { InstanceDetailTabKey } from './tabs'
|
||||
import type { NavIcon } from '@/app/components/app-sidebar/nav-link'
|
||||
@ -28,16 +28,36 @@ type TailwindNavIconProps = PropsWithoutRef<ComponentProps<'svg'>> & {
|
||||
titleId?: string
|
||||
}
|
||||
|
||||
const OverviewIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-dashboard-2-line', className)} />
|
||||
const OverviewSelectedIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-dashboard-2-fill', className)} />
|
||||
const DeployIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-rocket-line', className)} />
|
||||
const DeploySelectedIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-rocket-fill', className)} />
|
||||
const VersionsIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-stack-line', className)} />
|
||||
const VersionsSelectedIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-stack-fill', className)} />
|
||||
const AccessIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-plug-line', className)} />
|
||||
const AccessSelectedIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-plug-fill', className)} />
|
||||
const SettingsIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-settings-3-line', className)} />
|
||||
const SettingsSelectedIcon = ({ className }: TailwindNavIconProps) => <span aria-hidden className={cn('i-ri-settings-3-fill', className)} />
|
||||
function OverviewIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-dashboard-2-line', className)} />
|
||||
}
|
||||
function OverviewSelectedIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-dashboard-2-fill', className)} />
|
||||
}
|
||||
function DeployIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-rocket-line', className)} />
|
||||
}
|
||||
function DeploySelectedIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-rocket-fill', className)} />
|
||||
}
|
||||
function VersionsIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-stack-line', className)} />
|
||||
}
|
||||
function VersionsSelectedIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-stack-fill', className)} />
|
||||
}
|
||||
function AccessIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-plug-line', className)} />
|
||||
}
|
||||
function AccessSelectedIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-plug-fill', className)} />
|
||||
}
|
||||
function SettingsIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-settings-3-line', className)} />
|
||||
}
|
||||
function SettingsSelectedIcon({ className }: TailwindNavIconProps) {
|
||||
return <span aria-hidden className={cn('i-ri-settings-3-fill', className)} />
|
||||
}
|
||||
|
||||
const TABS: TabDef[] = [
|
||||
{ key: 'overview', icon: OverviewIcon, selectedIcon: OverviewSelectedIcon },
|
||||
@ -47,7 +67,7 @@ const TABS: TabDef[] = [
|
||||
{ key: 'settings', icon: SettingsIcon, selectedIcon: SettingsSelectedIcon },
|
||||
]
|
||||
|
||||
const isShortcutFromInputArea = (target: EventTarget | null) => {
|
||||
function isShortcutFromInputArea(target: EventTarget | null) {
|
||||
if (!(target instanceof HTMLElement))
|
||||
return false
|
||||
|
||||
@ -64,13 +84,13 @@ type DeploymentSidebarProps = {
|
||||
app?: AppInfo
|
||||
}
|
||||
|
||||
export const DeploymentSidebar: FC<DeploymentSidebarProps> = ({
|
||||
export function DeploymentSidebar({
|
||||
instanceId,
|
||||
instanceName,
|
||||
instanceDescription,
|
||||
appModeLabel,
|
||||
app,
|
||||
}) => {
|
||||
}: DeploymentSidebarProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const sidebarRef = useRef<HTMLDivElement>(null)
|
||||
const isHoveringSidebar = useHover(sidebarRef)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { InstanceDetailTabKey } from './tabs'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
@ -10,8 +10,8 @@ import { getAppModeLabel } from '@/app/components/app-sidebar/app-info/app-mode-
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { useRouter, useSelectedLayoutSegment } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import DeployDrawer from '../components/deploy-drawer'
|
||||
import RollbackModal from '../components/rollback-modal'
|
||||
import { DeployDrawer } from '../components/deploy-drawer'
|
||||
import { RollbackModal } from '../components/rollback-modal'
|
||||
import { toAppInfoFromOverview } from '../utils'
|
||||
import { DeploymentSidebar } from './deployment-sidebar'
|
||||
import { isInstanceDetailTabKey } from './tabs'
|
||||
@ -21,7 +21,7 @@ type InstanceDetailProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const InstanceDetail: FC<InstanceDetailProps> = ({ instanceId, children }) => {
|
||||
export function InstanceDetail({ instanceId, children }: InstanceDetailProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const { t: tCommon } = useTranslation()
|
||||
const router = useRouter()
|
||||
@ -95,5 +95,3 @@ const InstanceDetail: FC<InstanceDetailProps> = ({ instanceId, children }) => {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default InstanceDetail
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
@ -29,15 +29,17 @@ type SectionProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const Section: FC<SectionProps> = ({ title, action, children }) => (
|
||||
<div className="flex flex-col gap-3 rounded-xl border border-components-panel-border bg-components-panel-bg p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="system-sm-semibold text-text-primary">{title}</div>
|
||||
{action}
|
||||
function Section({ title, action, children }: SectionProps) {
|
||||
return (
|
||||
<div className="flex flex-col gap-3 rounded-xl border border-components-panel-border bg-components-panel-bg p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="system-sm-semibold text-text-primary">{title}</div>
|
||||
{action}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
type InfoRowProps = {
|
||||
label: string
|
||||
@ -45,12 +47,14 @@ type InfoRowProps = {
|
||||
mono?: boolean
|
||||
}
|
||||
|
||||
const InfoRow: FC<InfoRowProps> = ({ label, value, mono }) => (
|
||||
<div className="flex items-start gap-3 py-1.5">
|
||||
<span className="w-32 shrink-0 system-xs-regular text-text-tertiary">{label}</span>
|
||||
<span className={cn('min-w-0 flex-1 system-sm-regular text-text-primary', mono && 'font-mono')}>{value}</span>
|
||||
</div>
|
||||
)
|
||||
function InfoRow({ label, value, mono }: InfoRowProps) {
|
||||
return (
|
||||
<div className="flex items-start gap-3 py-1.5">
|
||||
<span className="w-32 shrink-0 system-xs-regular text-text-tertiary">{label}</span>
|
||||
<span className={cn('min-w-0 flex-1 system-sm-regular text-text-primary', mono && 'font-mono')}>{value}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type AccessOverviewRowProps = {
|
||||
label: string
|
||||
@ -59,7 +63,7 @@ type AccessOverviewRowProps = {
|
||||
meta?: string
|
||||
}
|
||||
|
||||
const AccessOverviewRow: FC<AccessOverviewRowProps> = ({ label, enabled, hint, meta }) => {
|
||||
function AccessOverviewRow({ label, enabled, hint, meta }: AccessOverviewRowProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
|
||||
return (
|
||||
@ -94,7 +98,7 @@ function overviewDeploymentStatus(status?: string) {
|
||||
return 'ready'
|
||||
}
|
||||
|
||||
const OverviewTab: FC<OverviewTabProps> = ({ instanceId }) => {
|
||||
export function OverviewTab({ instanceId }: OverviewTabProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const { t: tCommon } = useTranslation()
|
||||
const router = useRouter()
|
||||
@ -237,5 +241,3 @@ const OverviewTab: FC<OverviewTabProps> = ({ instanceId }) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default OverviewTab
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { AppInfo } from '../types'
|
||||
import type { GetAppInstanceSettingsReply } from '@/features/deployments/types'
|
||||
import {
|
||||
@ -35,7 +34,7 @@ type SettingsFormProps = {
|
||||
onDelete: () => Promise<void>
|
||||
}
|
||||
|
||||
const SettingsForm: FC<SettingsFormProps> = ({ app, settings, hasDeployments, onSave, onDelete }) => {
|
||||
function SettingsForm({ app, settings, hasDeployments, onSave, onDelete }: SettingsFormProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const [name, setName] = useState(settings?.name ?? app.name)
|
||||
const [description, setDescription] = useState(settings?.description ?? app.description ?? '')
|
||||
@ -175,7 +174,7 @@ const SettingsForm: FC<SettingsFormProps> = ({ app, settings, hasDeployments, on
|
||||
)
|
||||
}
|
||||
|
||||
const SettingsTab: FC<SettingsTabProps> = ({ instanceId }) => {
|
||||
export function SettingsTab({ instanceId }: SettingsTabProps) {
|
||||
const router = useRouter()
|
||||
const updateInstance = useMutation(consoleQuery.enterprise.appDeploy.updateAppInstance.mutationOptions())
|
||||
const deleteInstance = useMutation(consoleQuery.enterprise.appDeploy.deleteAppInstance.mutationOptions())
|
||||
@ -225,5 +224,3 @@ const SettingsTab: FC<SettingsTabProps> = ({ instanceId }) => {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default SettingsTab
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Dialog, DialogCloseButton, DialogContent, DialogDescription, DialogTitle } from '@langgenius/dify-ui/dialog'
|
||||
@ -28,7 +27,7 @@ type VersionsTabProps = {
|
||||
instanceId: string
|
||||
}
|
||||
|
||||
const VersionsTab: FC<VersionsTabProps> = ({ instanceId: appId }) => {
|
||||
export function VersionsTab({ instanceId: appId }: VersionsTabProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const input = { params: { appInstanceId: appId } }
|
||||
const { data: overview } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceOverview.queryOptions({
|
||||
@ -311,5 +310,3 @@ const VersionsTab: FC<VersionsTabProps> = ({ instanceId: appId }) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default VersionsTab
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import {
|
||||
DropdownMenu,
|
||||
@ -27,7 +26,7 @@ type DeployReleaseMenuProps = {
|
||||
releaseId: string
|
||||
}
|
||||
|
||||
export const DeployReleaseMenu: FC<DeployReleaseMenuProps> = ({ appInstanceId, releaseId }) => {
|
||||
export function DeployReleaseMenu({ appInstanceId, releaseId }: DeployReleaseMenuProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const openDeployDrawer = useDeploymentsStore(state => state.openDeployDrawer)
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import type { ReleaseDeployment, ReleaseDeploymentState } from './release-deployments'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
@ -16,7 +15,7 @@ type DeployedToBadgeProps = {
|
||||
item: ReleaseDeployment
|
||||
}
|
||||
|
||||
export const DeployedToBadge: FC<DeployedToBadgeProps> = ({ item }) => {
|
||||
export function DeployedToBadge({ item }: DeployedToBadgeProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const statusLabel = t(`versions.deployedStatus.${item.state}`)
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import {
|
||||
DropdownMenu,
|
||||
@ -24,7 +24,7 @@ type EnvironmentFilterProps = {
|
||||
onChange: (value: string) => void
|
||||
}
|
||||
|
||||
export const EnvironmentFilter: FC<EnvironmentFilterProps> = ({ value, options, onChange }) => {
|
||||
export function EnvironmentFilter({ value, options, onChange }: EnvironmentFilterProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const selectedOption = options.find(option => option.value === value) ?? options[0]
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useDebounce } from 'ahooks'
|
||||
import { debounce, parseAsString, useQueryState } from 'nuqs'
|
||||
@ -8,9 +7,9 @@ import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import CreateInstanceModal from '../components/create-instance-modal'
|
||||
import DeployDrawer from '../components/deploy-drawer'
|
||||
import RollbackModal from '../components/rollback-modal'
|
||||
import { CreateInstanceModal } from '../components/create-instance-modal'
|
||||
import { DeployDrawer } from '../components/deploy-drawer'
|
||||
import { RollbackModal } from '../components/rollback-modal'
|
||||
import { SOURCE_APPS_PAGE_SIZE } from '../data'
|
||||
import { useDeploymentsStore } from '../store'
|
||||
import {
|
||||
@ -21,7 +20,7 @@ import { EnvironmentFilter } from './environment-filter'
|
||||
import { InstanceCard } from './instance-card'
|
||||
import { NewInstanceCard } from './new-instance-card'
|
||||
|
||||
const DeploymentsMain: FC = () => {
|
||||
export function DeploymentsMain() {
|
||||
const { t } = useTranslation('deployments')
|
||||
const openCreateInstanceModal = useDeploymentsStore(state => state.openCreateInstanceModal)
|
||||
|
||||
@ -140,5 +139,3 @@ const DeploymentsMain: FC = () => {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DeploymentsMain
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { FC, MouseEvent } from 'react'
|
||||
import type { MouseEvent } from 'react'
|
||||
import type { AppInfo } from '../types'
|
||||
import type { AppDeploymentSummary } from '@/features/deployments/types'
|
||||
import type { AppModeEnum } from '@/types/app'
|
||||
@ -26,7 +26,7 @@ type InstanceCardProps = {
|
||||
summary?: AppDeploymentSummary
|
||||
}
|
||||
|
||||
export const InstanceCard: FC<InstanceCardProps> = ({ app, summary }) => {
|
||||
export function InstanceCard({ app, summary }: InstanceCardProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
const router = useRouter()
|
||||
const { formatTimeFromNow } = useFormatTimeFromNow()
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -15,7 +14,7 @@ type NewInstanceActionProps = {
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
const NewInstanceAction: FC<NewInstanceActionProps> = ({ icon, label, disabled, onClick }) => {
|
||||
function NewInstanceAction({ icon, label, disabled, onClick }: NewInstanceActionProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
|
||||
return (
|
||||
@ -42,7 +41,7 @@ const NewInstanceAction: FC<NewInstanceActionProps> = ({ icon, label, disabled,
|
||||
)
|
||||
}
|
||||
|
||||
export const NewInstanceCard: FC<NewInstanceCardProps> = ({ onOpen }) => {
|
||||
export function NewInstanceCard({ onOpen }: NewInstanceCardProps) {
|
||||
const { t } = useTranslation('deployments')
|
||||
return (
|
||||
<div className="relative col-span-1 inline-flex h-[160px] flex-col justify-between rounded-xl border-[0.5px] border-components-card-border bg-components-card-bg">
|
||||
|
||||
@ -15,7 +15,7 @@ import {
|
||||
toAppInfoFromOverview,
|
||||
} from '../utils'
|
||||
|
||||
const DeploymentsNav = () => {
|
||||
export function DeploymentsNav() {
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const selectedSegment = useSelectedLayoutSegment()
|
||||
@ -90,5 +90,3 @@ const DeploymentsNav = () => {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default DeploymentsNav
|
||||
|
||||
@ -16,60 +16,78 @@ import { PUBLIC_API_PREFIX } from '@/config'
|
||||
|
||||
export type DeploymentUiStatus = 'ready' | 'deploying' | 'deploy_failed'
|
||||
|
||||
export const formatDate = (value?: string) => {
|
||||
export function formatDate(value?: string) {
|
||||
if (!value)
|
||||
return '—'
|
||||
return value.replace('T', ' ').replace(/\.\d+Z?$/, '').replace(/Z$/, '').slice(0, 16)
|
||||
}
|
||||
|
||||
export const environmentId = (environment?: ConsoleEnvironmentSummary | EnvironmentOption) => environment?.id ?? ''
|
||||
export function environmentId(environment?: ConsoleEnvironmentSummary | EnvironmentOption) {
|
||||
return environment?.id ?? ''
|
||||
}
|
||||
|
||||
export const environmentName = (environment?: ConsoleEnvironmentSummary | EnvironmentOption) => environment?.name || environment?.id || '—'
|
||||
export function environmentName(environment?: ConsoleEnvironmentSummary | EnvironmentOption) {
|
||||
return environment?.name || environment?.id || '—'
|
||||
}
|
||||
|
||||
export const environmentMode = (environment?: ConsoleEnvironmentSummary | EnvironmentOption) => {
|
||||
export function environmentMode(environment?: ConsoleEnvironmentSummary | EnvironmentOption) {
|
||||
const type = environment?.type?.toLowerCase() ?? ''
|
||||
return type.includes('isolated') ? 'isolated' : 'shared'
|
||||
}
|
||||
|
||||
export const environmentBackend = (environment?: ConsoleEnvironmentSummary) => {
|
||||
export function environmentBackend(environment?: ConsoleEnvironmentSummary) {
|
||||
const runtime = (environment?.backend || environment?.runtime)?.toLowerCase() ?? ''
|
||||
return runtime.includes('host') ? 'host' : 'k8s'
|
||||
}
|
||||
|
||||
export const environmentHealth = (environment?: ConsoleEnvironmentSummary | EnvironmentOption) => {
|
||||
export function environmentHealth(environment?: ConsoleEnvironmentSummary | EnvironmentOption) {
|
||||
const status = environment?.status?.toLowerCase() ?? ''
|
||||
return status.includes('ready') ? 'ready' : 'degraded'
|
||||
}
|
||||
|
||||
export const releaseId = (release?: ConsoleReleaseSummary) => release?.id ?? ''
|
||||
export function releaseId(release?: ConsoleReleaseSummary) {
|
||||
return release?.id ?? ''
|
||||
}
|
||||
|
||||
export const releaseLabel = (release?: ConsoleReleaseSummary) => release?.name || release?.displayId || release?.id || '—'
|
||||
export function releaseLabel(release?: ConsoleReleaseSummary) {
|
||||
return release?.name || release?.displayId || release?.id || '—'
|
||||
}
|
||||
|
||||
export const releaseCommit = (release?: ConsoleReleaseSummary) => release?.shortCommitId || release?.commitId || '—'
|
||||
export function releaseCommit(release?: ConsoleReleaseSummary) {
|
||||
return release?.shortCommitId || release?.commitId || '—'
|
||||
}
|
||||
|
||||
export const runtimeBindingLabel = (binding?: RuntimeBindingDisplay) =>
|
||||
binding?.label || binding?.slot || binding?.kind || '—'
|
||||
export function runtimeBindingLabel(binding?: RuntimeBindingDisplay) {
|
||||
return binding?.label || binding?.slot || binding?.kind || '—'
|
||||
}
|
||||
|
||||
export const runtimeBindingValue = (binding?: RuntimeBindingDisplay) =>
|
||||
binding?.displayValue || binding?.maskedValue || binding?.displayName || '—'
|
||||
export function runtimeBindingValue(binding?: RuntimeBindingDisplay) {
|
||||
return binding?.displayValue || binding?.maskedValue || binding?.displayName || '—'
|
||||
}
|
||||
|
||||
export const runtimeBindingSummary = (binding?: RuntimeBindingDisplay) =>
|
||||
binding?.label || binding?.slot || binding?.displayName || binding?.displayValue || binding?.maskedValue || binding?.kind || '—'
|
||||
export function runtimeBindingSummary(binding?: RuntimeBindingDisplay) {
|
||||
return binding?.label || binding?.slot || binding?.displayName || binding?.displayValue || binding?.maskedValue || binding?.kind || '—'
|
||||
}
|
||||
|
||||
export const isRuntimeEnvVarBinding = (binding?: RuntimeBindingDisplay) =>
|
||||
(binding?.kind?.toLowerCase() ?? '').includes('env')
|
||||
export function isRuntimeEnvVarBinding(binding?: RuntimeBindingDisplay) {
|
||||
return (binding?.kind?.toLowerCase() ?? '').includes('env')
|
||||
}
|
||||
|
||||
export const isRuntimeModelBinding = (binding?: RuntimeBindingDisplay) =>
|
||||
(binding?.kind?.toLowerCase() ?? '').includes('model')
|
||||
export function isRuntimeModelBinding(binding?: RuntimeBindingDisplay) {
|
||||
return (binding?.kind?.toLowerCase() ?? '').includes('model')
|
||||
}
|
||||
|
||||
export const isRuntimePluginBinding = (binding?: RuntimeBindingDisplay) =>
|
||||
!isRuntimeEnvVarBinding(binding) && !isRuntimeModelBinding(binding)
|
||||
export function isRuntimePluginBinding(binding?: RuntimeBindingDisplay) {
|
||||
return !isRuntimeEnvVarBinding(binding) && !isRuntimeModelBinding(binding)
|
||||
}
|
||||
|
||||
const absoluteUrlRegExp = /^[a-z][a-z\d+.-]*:\/\//i
|
||||
|
||||
const withLeadingSlash = (path: string) => path.startsWith('/') ? path : `/${path}`
|
||||
function withLeadingSlash(path: string) {
|
||||
return path.startsWith('/') ? path : `/${path}`
|
||||
}
|
||||
|
||||
const publicWebappOrigin = () => {
|
||||
function publicWebappOrigin() {
|
||||
try {
|
||||
return new URL(PUBLIC_API_PREFIX).origin
|
||||
}
|
||||
@ -78,7 +96,7 @@ const publicWebappOrigin = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const webappUrl = (url?: string) => {
|
||||
export function webappUrl(url?: string) {
|
||||
if (!url)
|
||||
return ''
|
||||
if (absoluteUrlRegExp.test(url))
|
||||
@ -88,15 +106,19 @@ export const webappUrl = (url?: string) => {
|
||||
return `${origin}${withLeadingSlash(url)}`
|
||||
}
|
||||
|
||||
export const deploymentId = (row?: EnvironmentDeploymentRow) =>
|
||||
row?.id || ''
|
||||
export function deploymentId(row?: EnvironmentDeploymentRow) {
|
||||
return row?.id || ''
|
||||
}
|
||||
|
||||
export const activeRelease = (row?: EnvironmentDeploymentRow) => row?.currentRelease
|
||||
export function activeRelease(row?: EnvironmentDeploymentRow) {
|
||||
return row?.currentRelease
|
||||
}
|
||||
|
||||
export const isUndeployedDeploymentRow = (row?: EnvironmentDeploymentRow) =>
|
||||
(row?.status?.toLowerCase() ?? '').includes('undeployed') || (!row?.id && !row?.currentRelease && !row?.detail)
|
||||
export function isUndeployedDeploymentRow(row?: EnvironmentDeploymentRow) {
|
||||
return (row?.status?.toLowerCase() ?? '').includes('undeployed') || (!row?.id && !row?.currentRelease && !row?.detail)
|
||||
}
|
||||
|
||||
export const deploymentStatus = (row: EnvironmentDeploymentRow): DeploymentUiStatus => {
|
||||
export function deploymentStatus(row: EnvironmentDeploymentRow): DeploymentUiStatus {
|
||||
const runtimeStatus = row.status?.toLowerCase() ?? ''
|
||||
if (runtimeStatus.includes('deploying') || runtimeStatus.includes('pending'))
|
||||
return 'deploying'
|
||||
@ -105,13 +127,14 @@ export const deploymentStatus = (row: EnvironmentDeploymentRow): DeploymentUiSta
|
||||
return 'ready'
|
||||
}
|
||||
|
||||
export const deployedRows = (rows?: EnvironmentDeploymentRow[]) =>
|
||||
rows?.filter((row) => {
|
||||
export function deployedRows(rows?: EnvironmentDeploymentRow[]) {
|
||||
return rows?.filter((row) => {
|
||||
const runtimeStatus = row.status?.toLowerCase() ?? ''
|
||||
return row.environment?.id
|
||||
&& !isUndeployedDeploymentRow(row)
|
||||
&& (row.id || runtimeStatus || row.currentRelease || row.detail)
|
||||
}) ?? []
|
||||
}
|
||||
|
||||
export function toAppInfoFromSummary(summary: AppDeploymentSummary): AppInfo | undefined {
|
||||
if (!summary.id || !summary.name)
|
||||
@ -149,13 +172,13 @@ export function toAppInfoFromOverview(instance?: AppInstanceOverview): AppInfo |
|
||||
}
|
||||
}
|
||||
|
||||
export const sourceAppsFromList = (response?: ListAppDeploymentsReply) => {
|
||||
export function sourceAppsFromList(response?: ListAppDeploymentsReply) {
|
||||
return (response?.data ?? [])
|
||||
.map(toAppInfoFromSummary)
|
||||
.filter((app): app is AppInfo => Boolean(app))
|
||||
}
|
||||
|
||||
export const deploymentSummariesFromList = (response?: ListAppDeploymentsReply): Record<string, AppDeploymentSummary> => {
|
||||
export function deploymentSummariesFromList(response?: ListAppDeploymentsReply): Record<string, AppDeploymentSummary> {
|
||||
return Object.fromEntries(
|
||||
(response?.data ?? [])
|
||||
.filter(summary => summary.id)
|
||||
@ -163,7 +186,7 @@ export const deploymentSummariesFromList = (response?: ListAppDeploymentsReply):
|
||||
)
|
||||
}
|
||||
|
||||
export const environmentOptionsFromOptionsReply = (response?: ListDeploymentEnvironmentOptionsReply): EnvironmentOption[] => {
|
||||
export function environmentOptionsFromOptionsReply(response?: ListDeploymentEnvironmentOptionsReply): EnvironmentOption[] {
|
||||
return response?.environments
|
||||
?.filter(environment => environment.id)
|
||||
.map(environment => ({
|
||||
@ -172,7 +195,7 @@ export const environmentOptionsFromOptionsReply = (response?: ListDeploymentEnvi
|
||||
})) ?? []
|
||||
}
|
||||
|
||||
export const accessModeToPermissionKey = (mode?: string): AccessPermissionKind => {
|
||||
export function accessModeToPermissionKey(mode?: string): AccessPermissionKind {
|
||||
const normalized = mode?.toLowerCase() ?? ''
|
||||
if (normalized === 'private')
|
||||
return 'specific'
|
||||
@ -181,7 +204,7 @@ export const accessModeToPermissionKey = (mode?: string): AccessPermissionKind =
|
||||
return 'organization'
|
||||
}
|
||||
|
||||
export const permissionKeyToAccessMode = (key: AccessPermissionKind) => {
|
||||
export function permissionKeyToAccessMode(key: AccessPermissionKind) {
|
||||
if (key === 'organization')
|
||||
return 'private_all'
|
||||
if (key === 'specific')
|
||||
|
||||
@ -17,9 +17,11 @@ import {
|
||||
import { isClient } from '@/utils/client'
|
||||
import { request } from './base'
|
||||
|
||||
const getMarketplaceHeaders = () => new Headers({
|
||||
'X-Dify-Version': !IS_MARKETPLACE ? APP_VERSION : '999.0.0',
|
||||
})
|
||||
function getMarketplaceHeaders() {
|
||||
return new Headers({
|
||||
'X-Dify-Version': !IS_MARKETPLACE ? APP_VERSION : '999.0.0',
|
||||
})
|
||||
}
|
||||
|
||||
function isURL(path: string) {
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user