init create page

This commit is contained in:
Stephen Zhou
2026-05-18 16:22:38 +08:00
parent 4c0ff8782b
commit edce7717cb
6 changed files with 1231 additions and 77 deletions

View File

@ -0,0 +1,12 @@
'use client'
import { useTranslation } from 'react-i18next'
import { CreateDeploymentGuide } from '@/features/deployments/create-guide'
import useDocumentTitle from '@/hooks/use-document-title'
export default function CreateDeploymentPage() {
const { t } = useTranslation('deployments')
useDocumentTitle(t('documentTitle.create'))
return <CreateDeploymentGuide />
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
'use client'
import { useTranslation } from 'react-i18next'
import Link from '@/next/link'
export function CreateDeploymentButton() {
const { t } = useTranslation('deployments')
return (
<Link
href="/deployments/create"
className="inline-flex h-8 items-center gap-1.5 rounded-lg bg-primary-600 px-3 system-sm-medium text-text-primary-on-surface hover:bg-primary-700"
>
<span className="i-ri-add-line size-4 shrink-0" aria-hidden="true" />
<span>{t('list.createDeployment')}</span>
</Link>
)
}

View File

@ -10,9 +10,9 @@ import Input from '@/app/components/base/input'
import { SkeletonRectangle } from '@/app/components/base/skeleton'
import { consoleQuery } from '@/service/client'
import { getNextPageParamFromPagination, SOURCE_APPS_PAGE_SIZE } from '../data'
import { CreateDeploymentButton } from './create-deployment-button'
import { EnvironmentFilter } from './environment-filter'
import { InstanceCard } from './instance-card'
import { NewInstanceCard } from './new-instance-card'
import { envFilterQueryState, keywordsQueryState } from './query-state'
const INSTANCE_CARD_SKELETON_KEYS = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
@ -114,7 +114,8 @@ function DeploymentsSearchInput() {
function DeploymentsListControls() {
return (
<div className="sticky top-0 z-10 flex flex-wrap items-center justify-end gap-y-2 bg-background-body px-12 pt-7 pb-5">
<div className="sticky top-0 z-10 flex flex-wrap items-center justify-between gap-3 bg-background-body px-12 pt-7 pb-5">
<CreateDeploymentButton />
<div className="flex items-center gap-2">
<EnvironmentFilter />
<DeploymentsSearchInput />
@ -190,7 +191,6 @@ export function DeploymentsList() {
showEmptyState && 'overflow-hidden',
)}
>
<NewInstanceCard />
{showSkeleton
? <DeploymentsListSkeleton />
: isError

View File

@ -1,74 +0,0 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { CreateInstanceModal } from '../components/create-instance-modal'
function NewInstanceAction({ icon, label, disabled, onClick }: {
icon: string
label: string
disabled?: boolean
onClick?: () => void
}) {
const { t } = useTranslation('deployments')
return (
<button
type="button"
onClick={disabled ? undefined : onClick}
disabled={disabled}
title={disabled ? t('newInstance.comingSoon') : undefined}
className={cn(
'flex h-8 w-full items-center gap-2 rounded-lg px-6 text-left system-sm-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
disabled
? 'cursor-not-allowed opacity-50 hover:bg-transparent hover:text-text-tertiary'
: 'cursor-pointer',
)}
>
<span aria-hidden className={cn('size-4 shrink-0', icon)} />
<span className="min-w-0 flex-1 truncate">{label}</span>
{disabled && (
<span className="shrink-0 rounded-md bg-state-base-hover px-1.5 system-2xs-medium text-text-tertiary">
{t('newInstance.comingSoon')}
</span>
)}
</button>
)
}
function CreateFromStudioAction() {
const { t } = useTranslation('deployments')
const [createModalOpen, setCreateModalOpen] = useState(false)
return (
<>
<NewInstanceAction
icon="i-ri-stack-line"
label={t('newInstance.fromStudio')}
onClick={() => setCreateModalOpen(true)}
/>
<CreateInstanceModal open={createModalOpen} onOpenChange={setCreateModalOpen} />
</>
)
}
export function NewInstanceCard() {
const { t } = useTranslation('deployments')
return (
<div className="relative col-span-1 inline-flex h-40 flex-col justify-between rounded-xl border border-components-card-border bg-components-card-bg">
<div className="flex grow flex-col gap-1 rounded-t-xl p-2">
<div className="px-6 pt-2 pb-1 text-xs/[18px] font-medium text-text-tertiary">
{t('newInstance.title')}
</div>
<CreateFromStudioAction />
<NewInstanceAction
icon="i-ri-file-code-line"
label={t('newInstance.importDSL')}
disabled
/>
</div>
</div>
)
}

View File

@ -93,6 +93,72 @@
"card.tooltip.notDeployed": "This instance has not been deployed to any environment yet.",
"common.loadFailed": "Failed to load. Try again later.",
"common.loading": "Loading...",
"createGuide.actions.back": "Back",
"createGuide.actions.cancel": "Cancel",
"createGuide.actions.continue": "Continue",
"createGuide.actions.createAndDeploy": "Create and deploy",
"createGuide.actions.deploying": "Deploying...",
"createGuide.description": "Create a usable deployment through source, release, bindings, and environment selection.",
"createGuide.done.backToList": "Back to deployments",
"createGuide.done.description": "Deployment has started for {{environment}}.",
"createGuide.done.next": "You can review status, access, and release history from the deployments list.",
"createGuide.done.ready": "The deployment request has been submitted.",
"createGuide.done.title": "Deployment started",
"createGuide.dsl.defaultAppName": "Imported DSL app",
"createGuide.dsl.description": "Prepare an app instance from a DSL package. Import execution will be wired when the backend API is ready.",
"createGuide.dsl.dropDescription": "DSL import is a UI placeholder for now. The final deploy action will stay disabled from real import work until the API is available.",
"createGuide.dsl.dropTitle": "Upload DSL package",
"createGuide.dsl.title": "Import DSL",
"createGuide.errors.deployFailed": "Failed to create and deploy the app instance.",
"createGuide.method.description": "Start from an app already in Studio or prepare a deployment from a DSL package.",
"createGuide.methods.bindApp.description": "Use an app that already exists in Studio as the release source.",
"createGuide.methods.bindApp.title": "Bind existing Studio app",
"createGuide.methods.importDsl.description": "Upload a YAML DSL package and continue through the deployment UI.",
"createGuide.methods.importDsl.title": "Import DSL",
"createGuide.methods.mocked": "Mocked",
"createGuide.nav.back": "Deployments",
"createGuide.release.defaultNote": "Initial deployable release",
"createGuide.release.description": "Name the deployable instance and capture the first release metadata.",
"createGuide.release.instanceName": "Instance name",
"createGuide.release.releaseName": "Release name",
"createGuide.release.releaseNote": "Release note",
"createGuide.release.title": "Create release",
"createGuide.review.bindings": "Runtime bindings",
"createGuide.review.description": "Confirm the source, release, credentials, and target environment before deployment.",
"createGuide.review.environment": "Environment",
"createGuide.review.instance": "Instance",
"createGuide.review.plan.createInstance": "Create the app instance",
"createGuide.review.plan.createRelease": "Create release {{release}}",
"createGuide.review.plan.deployTo": "Deploy to {{environment}}",
"createGuide.review.plan.resolveBindings": "Resolve runtime credentials",
"createGuide.review.planTitle": "Execution plan",
"createGuide.review.release": "Release",
"createGuide.review.releaseNote": "Release note",
"createGuide.review.source": "Source",
"createGuide.review.summary": "Deployment summary",
"createGuide.review.title": "Review deployment",
"createGuide.source.description": "Choose the Studio app that will become the first release source.",
"createGuide.source.empty": "No Studio apps found.",
"createGuide.source.searchPlaceholder": "Search apps",
"createGuide.source.sourceApp": "Source app",
"createGuide.source.title": "Choose source",
"createGuide.steps.done": "Done",
"createGuide.steps.method": "Select a method",
"createGuide.steps.release": "Create release",
"createGuide.steps.review": "Create and deploy",
"createGuide.steps.source": "Choose source",
"createGuide.steps.target": "Deploy target",
"createGuide.target.bindingHint": "Pick the credentials that will be used when this release runs.",
"createGuide.target.bindings": "Runtime bindings",
"createGuide.target.description": "Select the runtime environment and resolve the credentials used by the release.",
"createGuide.target.environment": "Target environment",
"createGuide.target.missingRequiredBinding": "Select a credential for this required binding.",
"createGuide.target.noBindingRequired": "No runtime binding required.",
"createGuide.target.noCredentialCandidates": "No available credentials.",
"createGuide.target.required": "Required",
"createGuide.target.selectCredential": "Select a credential",
"createGuide.target.title": "Select deploy target",
"createGuide.title": "Create deployment",
"createModal.appPickerPlaceholder": "Select a source app",
"createModal.appSearchEmpty": "No matching apps",
"createModal.appSearchPlaceholder": "Search apps…",
@ -217,6 +283,7 @@
"detail.sourceApp": "Source app",
"detail.sourceAppDeleted": "Source app deleted",
"detail.sourceAppLink": "Source app",
"documentTitle.create": "Create deployment · Deployments",
"documentTitle.detail": "Instance · Deployments",
"documentTitle.list": "Deployments",
"filter.allEnvs": "All environments",
@ -224,6 +291,7 @@
"filter.searchPlaceholder": "Search instances",
"health.degraded": "Degraded",
"health.ready": "Ready",
"list.createDeployment": "Create deployment",
"list.empty": "No app instances found.",
"mode.isolated": "Isolated",
"mode.shared": "Shared",