Commit 9bca69eb authored by JzoNg's avatar JzoNg

app DSL export supported

parent b33da6a0
...@@ -13,7 +13,7 @@ import type { ConfigParams } from '@/app/components/app/overview/settings' ...@@ -13,7 +13,7 @@ import type { ConfigParams } from '@/app/components/app/overview/settings'
import type { App } from '@/types/app' import type { App } from '@/types/app'
import Confirm from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm'
import { ToastContext } from '@/app/components/base/toast' import { ToastContext } from '@/app/components/base/toast'
import { copyApp, deleteApp, fetchAppDetail, updateAppSiteConfig } from '@/service/apps' import { copyApp, deleteApp, exportAppConfig, fetchAppDetail, updateAppSiteConfig } from '@/service/apps'
import DuplicateAppModal from '@/app/components/app/duplicate-modal' import DuplicateAppModal from '@/app/components/app/duplicate-modal'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal' import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
import AppIcon from '@/app/components/base/app-icon' import AppIcon from '@/app/components/base/app-icon'
...@@ -135,6 +135,20 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => { ...@@ -135,6 +135,20 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
} }
} }
const onExport = async () => {
try {
const { data } = await exportAppConfig(app.id)
const a = document.createElement('a')
const file = new Blob([data], { type: 'application/yaml' })
a.href = URL.createObjectURL(file)
a.download = `${app.name}.yml`
a.click()
}
catch (e) {
notify({ type: 'error', message: t('app.exportFailed') })
}
}
const Operations = (props: HtmlContentProps) => { const Operations = (props: HtmlContentProps) => {
const onClickSettings = async (e: React.MouseEvent<HTMLButtonElement>) => { const onClickSettings = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation() e.stopPropagation()
...@@ -153,7 +167,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => { ...@@ -153,7 +167,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
e.stopPropagation() e.stopPropagation()
props.onClick?.() props.onClick?.()
e.preventDefault() e.preventDefault()
// TODO export onExport()
} }
const onClickDelete = async (e: React.MouseEvent<HTMLDivElement>) => { const onClickDelete = async (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation() e.stopPropagation()
......
...@@ -10,6 +10,7 @@ const translation = { ...@@ -10,6 +10,7 @@ const translation = {
duplicate: 'Duplicate', duplicate: 'Duplicate',
duplicateTitle: 'Duplicate App', duplicateTitle: 'Duplicate App',
export: 'Export DSL', export: 'Export DSL',
exportFailed: 'Export DSL failed.',
createFromConfigFile: 'Create from DSL file', createFromConfigFile: 'Create from DSL file',
deleteAppConfirmTitle: 'Delete this app?', deleteAppConfirmTitle: 'Delete this app?',
deleteAppConfirmContent: deleteAppConfirmContent:
......
...@@ -10,6 +10,7 @@ const translation = { ...@@ -10,6 +10,7 @@ const translation = {
duplicate: '复制', duplicate: '复制',
duplicateTitle: '复制应用', duplicateTitle: '复制应用',
export: '导出 DSL', export: '导出 DSL',
exportFailed: '导出 DSL 失败',
createFromConfigFile: '通过 DSL 文件创建', createFromConfigFile: '通过 DSL 文件创建',
deleteAppConfirmTitle: '确认删除应用?', deleteAppConfirmTitle: '确认删除应用?',
deleteAppConfirmContent: deleteAppConfirmContent:
......
...@@ -19,10 +19,15 @@ export const fetchAppTemplates: Fetcher<AppTemplatesResponse, { url: string }> = ...@@ -19,10 +19,15 @@ export const fetchAppTemplates: Fetcher<AppTemplatesResponse, { url: string }> =
export const createApp: Fetcher<AppDetailResponse, { name: string; icon: string; icon_background: string; mode: AppMode; description?: string; config?: ModelConfig }> = ({ name, icon, icon_background, mode, description, config }) => { export const createApp: Fetcher<AppDetailResponse, { name: string; icon: string; icon_background: string; mode: AppMode; description?: string; config?: ModelConfig }> = ({ name, icon, icon_background, mode, description, config }) => {
return post<AppDetailResponse>('apps', { body: { name, icon, icon_background, mode, description, model_config: config } }) return post<AppDetailResponse>('apps', { body: { name, icon, icon_background, mode, description, model_config: config } })
} }
export const copyApp: Fetcher<AppDetailResponse, { appID: string; name: string; icon: string; icon_background: string; mode: AppMode; description?: string }> = ({ appID, name, icon, icon_background, mode, description }) => { export const copyApp: Fetcher<AppDetailResponse, { appID: string; name: string; icon: string; icon_background: string; mode: AppMode; description?: string }> = ({ appID, name, icon, icon_background, mode, description }) => {
return post<AppDetailResponse>(`apps/${appID}/copy`, { body: { name, icon, icon_background, mode, description } }) return post<AppDetailResponse>(`apps/${appID}/copy`, { body: { name, icon, icon_background, mode, description } })
} }
export const exportAppConfig: Fetcher<{ data: string }, string> = (appID) => {
return post<{ data: string }>(`apps/${appID}/export`)
}
export const deleteApp: Fetcher<CommonResponse, string> = (appID) => { export const deleteApp: Fetcher<CommonResponse, string> = (appID) => {
return del<CommonResponse>(`apps/${appID}`) return del<CommonResponse>(`apps/${appID}`)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment