|
|
|
@ -3,35 +3,29 @@ import { useMemo, useRef, useState } from 'react'
|
|
|
|
import { useRouter } from 'next/navigation'
|
|
|
|
import { useRouter } from 'next/navigation'
|
|
|
|
import { useContext } from 'use-context-selector'
|
|
|
|
import { useContext } from 'use-context-selector'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { RiCloseLine, RiCommandLine, RiCornerDownLeftLine } from '@remixicon/react'
|
|
|
|
|
|
|
|
import { useDebounceFn, useKeyPress } from 'ahooks'
|
|
|
|
import { useDebounceFn, useKeyPress } from 'ahooks'
|
|
|
|
import Button from '@/app/components/base/button'
|
|
|
|
import Button from '@/app/components/base/button'
|
|
|
|
import Input from '@/app/components/base/input'
|
|
|
|
import Input from '@/app/components/base/input'
|
|
|
|
import Modal from '@/app/components/base/modal'
|
|
|
|
import Modal from '@/app/components/base/modal'
|
|
|
|
import { ToastContext } from '@/app/components/base/toast'
|
|
|
|
import { ToastContext } from '@/app/components/base/toast'
|
|
|
|
import {
|
|
|
|
|
|
|
|
importDSL,
|
|
|
|
|
|
|
|
importDSLConfirm,
|
|
|
|
|
|
|
|
} from '@/service/apps'
|
|
|
|
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
DSLImportMode,
|
|
|
|
DSLImportMode,
|
|
|
|
DSLImportStatus,
|
|
|
|
DSLImportStatus,
|
|
|
|
} from '@/models/app'
|
|
|
|
} from '@/models/app'
|
|
|
|
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
|
|
|
|
|
|
|
|
import { useProviderContextSelector } from '@/context/provider-context'
|
|
|
|
import { useProviderContextSelector } from '@/context/provider-context'
|
|
|
|
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
|
|
|
|
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
|
|
|
|
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
|
|
|
|
|
|
|
import { getRedirection } from '@/utils/app-redirection'
|
|
|
|
|
|
|
|
import cn from '@/utils/classnames'
|
|
|
|
|
|
|
|
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
|
|
|
|
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
|
|
|
|
import { noop } from 'lodash-es'
|
|
|
|
import { noop } from 'lodash-es'
|
|
|
|
import Uploader from './uploader'
|
|
|
|
import Uploader from './uploader'
|
|
|
|
|
|
|
|
import Header from './header'
|
|
|
|
|
|
|
|
import Tab from './tab'
|
|
|
|
|
|
|
|
import { useImportPipelineDSL, useImportPipelineDSLConfirm } from '@/service/use-pipeline'
|
|
|
|
|
|
|
|
|
|
|
|
type CreateFromDSLModalProps = {
|
|
|
|
type CreateFromDSLModalProps = {
|
|
|
|
show: boolean
|
|
|
|
show: boolean
|
|
|
|
onSuccess?: () => void
|
|
|
|
onSuccess?: () => void
|
|
|
|
onClose: () => void
|
|
|
|
onClose: () => void
|
|
|
|
activeTab?: string
|
|
|
|
activeTab?: CreateFromDSLModalTab
|
|
|
|
dslUrl?: string
|
|
|
|
dslUrl?: string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -76,14 +70,14 @@ const CreateFromDSLModal = ({
|
|
|
|
setFileContent('')
|
|
|
|
setFileContent('')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const isCurrentWorkspaceEditor = useAppContextWithSelector(state => state.isCurrentWorkspaceEditor)
|
|
|
|
|
|
|
|
const plan = useProviderContextSelector(state => state.plan)
|
|
|
|
const plan = useProviderContextSelector(state => state.plan)
|
|
|
|
const enableBilling = useProviderContextSelector(state => state.enableBilling)
|
|
|
|
const enableBilling = useProviderContextSelector(state => state.enableBilling)
|
|
|
|
const isAppsFull = (enableBilling && plan.usage.buildApps >= plan.total.buildApps)
|
|
|
|
const isAppsFull = (enableBilling && plan.usage.buildApps >= plan.total.buildApps)
|
|
|
|
|
|
|
|
|
|
|
|
const isCreatingRef = useRef(false)
|
|
|
|
const isCreatingRef = useRef(false)
|
|
|
|
|
|
|
|
|
|
|
|
// todo: replace with pipeline import DSL and check plugin dependencies
|
|
|
|
const { mutateAsync: importDSL } = useImportPipelineDSL()
|
|
|
|
|
|
|
|
|
|
|
|
const onCreate = async () => {
|
|
|
|
const onCreate = async () => {
|
|
|
|
if (currentTab === CreateFromDSLModalTab.FROM_FILE && !currentFile)
|
|
|
|
if (currentTab === CreateFromDSLModalTab.FROM_FILE && !currentFile)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
@ -94,7 +88,6 @@ const CreateFromDSLModal = ({
|
|
|
|
isCreatingRef.current = true
|
|
|
|
isCreatingRef.current = true
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
let response
|
|
|
|
let response
|
|
|
|
|
|
|
|
|
|
|
|
if (currentTab === CreateFromDSLModalTab.FROM_FILE) {
|
|
|
|
if (currentTab === CreateFromDSLModalTab.FROM_FILE) {
|
|
|
|
response = await importDSL({
|
|
|
|
response = await importDSL({
|
|
|
|
mode: DSLImportMode.YAML_CONTENT,
|
|
|
|
mode: DSLImportMode.YAML_CONTENT,
|
|
|
|
@ -110,7 +103,7 @@ const CreateFromDSLModal = ({
|
|
|
|
|
|
|
|
|
|
|
|
if (!response)
|
|
|
|
if (!response)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
const { id, status, app_id, app_mode, imported_dsl_version, current_dsl_version } = response
|
|
|
|
const { id, status, pipeline_id, imported_dsl_version, current_dsl_version } = response
|
|
|
|
if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
|
|
|
|
if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
|
|
|
|
if (onSuccess)
|
|
|
|
if (onSuccess)
|
|
|
|
onSuccess()
|
|
|
|
onSuccess()
|
|
|
|
@ -122,9 +115,9 @@ const CreateFromDSLModal = ({
|
|
|
|
message: t(status === DSLImportStatus.COMPLETED ? 'app.newApp.appCreated' : 'app.newApp.caution'),
|
|
|
|
message: t(status === DSLImportStatus.COMPLETED ? 'app.newApp.appCreated' : 'app.newApp.caution'),
|
|
|
|
children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('app.newApp.appCreateDSLWarning'),
|
|
|
|
children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('app.newApp.appCreateDSLWarning'),
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if (app_id)
|
|
|
|
if (pipeline_id)
|
|
|
|
await handleCheckPluginDependencies(app_id)
|
|
|
|
await handleCheckPluginDependencies(pipeline_id, true)
|
|
|
|
getRedirection(isCurrentWorkspaceEditor, { id: app_id!, mode: app_mode }, push)
|
|
|
|
push(`datasets/${pipeline_id}/pipeline`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (status === DSLImportStatus.PENDING) {
|
|
|
|
else if (status === DSLImportStatus.PENDING) {
|
|
|
|
setVersions({
|
|
|
|
setVersions({
|
|
|
|
@ -142,8 +135,7 @@ const CreateFromDSLModal = ({
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
|
|
catch {
|
|
|
|
catch (e) {
|
|
|
|
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
finally {
|
|
|
|
@ -153,16 +145,13 @@ const CreateFromDSLModal = ({
|
|
|
|
|
|
|
|
|
|
|
|
const { run: handleCreateApp } = useDebounceFn(onCreate, { wait: 300 })
|
|
|
|
const { run: handleCreateApp } = useDebounceFn(onCreate, { wait: 300 })
|
|
|
|
|
|
|
|
|
|
|
|
useKeyPress(['meta.enter', 'ctrl.enter'], () => {
|
|
|
|
|
|
|
|
if (show && !isAppsFull && ((currentTab === CreateFromDSLModalTab.FROM_FILE && currentFile) || (currentTab === CreateFromDSLModalTab.FROM_URL && dslUrlValue)))
|
|
|
|
|
|
|
|
handleCreateApp()
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useKeyPress('esc', () => {
|
|
|
|
useKeyPress('esc', () => {
|
|
|
|
if (show && !showErrorModal)
|
|
|
|
if (show && !showErrorModal)
|
|
|
|
onClose()
|
|
|
|
onClose()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { mutateAsync: importDSLConfirm } = useImportPipelineDSLConfirm()
|
|
|
|
|
|
|
|
|
|
|
|
const onDSLConfirm = async () => {
|
|
|
|
const onDSLConfirm = async () => {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
if (!importId)
|
|
|
|
if (!importId)
|
|
|
|
@ -171,7 +160,7 @@ const CreateFromDSLModal = ({
|
|
|
|
import_id: importId,
|
|
|
|
import_id: importId,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const { status, app_id, app_mode } = response
|
|
|
|
const { status, pipeline_id } = response
|
|
|
|
|
|
|
|
|
|
|
|
if (status === DSLImportStatus.COMPLETED) {
|
|
|
|
if (status === DSLImportStatus.COMPLETED) {
|
|
|
|
if (onSuccess)
|
|
|
|
if (onSuccess)
|
|
|
|
@ -183,32 +172,19 @@ const CreateFromDSLModal = ({
|
|
|
|
type: 'success',
|
|
|
|
type: 'success',
|
|
|
|
message: t('app.newApp.appCreated'),
|
|
|
|
message: t('app.newApp.appCreated'),
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if (app_id)
|
|
|
|
if (pipeline_id)
|
|
|
|
await handleCheckPluginDependencies(app_id)
|
|
|
|
await handleCheckPluginDependencies(pipeline_id, true)
|
|
|
|
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
|
|
|
push(`datasets/${pipeline_id}/pipeline`)
|
|
|
|
getRedirection(isCurrentWorkspaceEditor, { id: app_id!, mode: app_mode }, push)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (status === DSLImportStatus.FAILED) {
|
|
|
|
else if (status === DSLImportStatus.FAILED) {
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
|
|
catch {
|
|
|
|
catch (e) {
|
|
|
|
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const tabs = [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
key: CreateFromDSLModalTab.FROM_FILE,
|
|
|
|
|
|
|
|
label: t('app.importFromDSLFile'),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
key: CreateFromDSLModalTab.FROM_URL,
|
|
|
|
|
|
|
|
label: t('app.importFromDSLUrl'),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const buttonDisabled = useMemo(() => {
|
|
|
|
const buttonDisabled = useMemo(() => {
|
|
|
|
if (isAppsFull)
|
|
|
|
if (isAppsFull)
|
|
|
|
return true
|
|
|
|
return true
|
|
|
|
@ -226,36 +202,11 @@ const CreateFromDSLModal = ({
|
|
|
|
isShow={show}
|
|
|
|
isShow={show}
|
|
|
|
onClose={noop}
|
|
|
|
onClose={noop}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<div className='title-2xl-semi-bold flex items-center justify-between pb-3 pl-6 pr-5 pt-6 text-text-primary'>
|
|
|
|
<Header onClose={onClose} />
|
|
|
|
{t('app.importFromDSL')}
|
|
|
|
<Tab
|
|
|
|
<div
|
|
|
|
currentTab={currentTab}
|
|
|
|
className='flex h-8 w-8 cursor-pointer items-center'
|
|
|
|
setCurrentTab={setCurrentTab}
|
|
|
|
onClick={() => onClose()}
|
|
|
|
/>
|
|
|
|
>
|
|
|
|
|
|
|
|
<RiCloseLine className='h-5 w-5 text-text-tertiary' />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className='system-md-semibold flex h-9 items-center space-x-6 border-b border-divider-subtle px-6 text-text-tertiary'>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tabs.map(tab => (
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
key={tab.key}
|
|
|
|
|
|
|
|
className={cn(
|
|
|
|
|
|
|
|
'relative flex h-full cursor-pointer items-center',
|
|
|
|
|
|
|
|
currentTab === tab.key && 'text-text-primary',
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
onClick={() => setCurrentTab(tab.key)}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{tab.label}
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
currentTab === tab.key && (
|
|
|
|
|
|
|
|
<div className='absolute bottom-0 h-[2px] w-full bg-util-colors-blue-brand-blue-brand-600'></div>
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className='px-6 py-4'>
|
|
|
|
<div className='px-6 py-4'>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
currentTab === CreateFromDSLModalTab.FROM_FILE && (
|
|
|
|
currentTab === CreateFromDSLModalTab.FROM_FILE && (
|
|
|
|
@ -284,19 +235,17 @@ const CreateFromDSLModal = ({
|
|
|
|
<AppsFull className='mt-0' loc='app-create-dsl' />
|
|
|
|
<AppsFull className='mt-0' loc='app-create-dsl' />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
<div className='flex justify-end px-6 py-5'>
|
|
|
|
<div className='flex justify-end gap-x-2 p-6 pt-5'>
|
|
|
|
<Button className='mr-2' onClick={onClose}>{t('app.newApp.Cancel')}</Button>
|
|
|
|
<Button onClick={onClose}>
|
|
|
|
|
|
|
|
{t('app.newApp.Cancel')}
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
<Button
|
|
|
|
<Button
|
|
|
|
disabled={buttonDisabled}
|
|
|
|
disabled={buttonDisabled}
|
|
|
|
variant='primary'
|
|
|
|
variant='primary'
|
|
|
|
onClick={handleCreateApp}
|
|
|
|
onClick={handleCreateApp}
|
|
|
|
className='gap-1'
|
|
|
|
className='gap-1'
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<span>{t('app.newApp.Create')}</span>
|
|
|
|
<span>{t('app.newApp.import')}</span>
|
|
|
|
<div className='flex gap-0.5'>
|
|
|
|
|
|
|
|
<RiCommandLine size={14} className='system-kbd rounded-sm bg-components-kbd-bg-white p-0.5' />
|
|
|
|
|
|
|
|
<RiCornerDownLeftLine size={14} className='system-kbd rounded-sm bg-components-kbd-bg-white p-0.5' />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Modal>
|
|
|
|
</Modal>
|
|
|
|
|