mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
@@ -31,7 +31,8 @@ const CustomRightDrawer = ({
|
||||
zIndex={100}
|
||||
maxW={maxW}
|
||||
w={'100%'}
|
||||
h={'90vh'}
|
||||
top={'60px'}
|
||||
bottom={0}
|
||||
borderLeftRadius={'lg'}
|
||||
border={'base'}
|
||||
boxShadow={'2'}
|
||||
|
@@ -92,6 +92,7 @@
|
||||
"plugin_dispatch_tip": "It is up to the model to decide which plug-ins to add additional capabilities to. If the plug-in is selected, the knowledge base call is also treated as a special plug-in.",
|
||||
"publish_channel": "Publish channel",
|
||||
"publish_success": "Publish success",
|
||||
"saved_success": "Saved success",
|
||||
"search_app": "Search app",
|
||||
"setting_app": "Settings",
|
||||
"setting_plugin": "Setting plugin",
|
||||
|
@@ -49,6 +49,7 @@
|
||||
"workflow": {
|
||||
"Back_to_current_version": "Back to current version",
|
||||
"My edit": "My edit",
|
||||
"Switch_failed": "Switch failed",
|
||||
"Switch_success": "switch successfully",
|
||||
"Team cloud": "Team cloud",
|
||||
"exit_tips": "Your changes have not been saved. Exiting directly will not save your edits."
|
||||
|
@@ -91,6 +91,7 @@
|
||||
"plugin_dispatch_tip": "给模型附加额外的能力,具体调用哪些插件,将由模型自主决定。\n若选择了插件,知识库调用将自动作为一个特殊的插件。",
|
||||
"publish_channel": "发布渠道",
|
||||
"publish_success": "发布成功",
|
||||
"saved_success": "保存成功",
|
||||
"search_app": "搜索应用",
|
||||
"setting_app": "应用配置",
|
||||
"setting_plugin": "插件配置",
|
||||
|
@@ -49,6 +49,7 @@
|
||||
"workflow": {
|
||||
"Back_to_current_version": "回到初始状态",
|
||||
"My edit": "我的编辑",
|
||||
"Switch_failed": "切换失败",
|
||||
"Switch_success": "切换成功",
|
||||
"Team cloud": "团队云端",
|
||||
"exit_tips": "您的更改尚未保存,「直接退出」将不会保存您的编辑记录。"
|
||||
|
22
projects/app/src/pages/api/core/app/version/detail.ts
Normal file
22
projects/app/src/pages/api/core/app/version/detail.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
|
||||
import { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
|
||||
type Props = {
|
||||
versionId: string;
|
||||
appId: string;
|
||||
};
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
const { versionId, appId } = req.query as Props;
|
||||
|
||||
await authApp({ req, authToken: true, appId, per: ReadPermissionVal });
|
||||
const result = await MongoAppVersion.findById(versionId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
56
projects/app/src/pages/api/core/app/version/listWorkflow.tsx
Normal file
56
projects/app/src/pages/api/core/app/version/listWorkflow.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
|
||||
import { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
|
||||
type Props = PaginationProps<{
|
||||
appId: string;
|
||||
}>;
|
||||
|
||||
export type versionListResponse = {
|
||||
_id: string;
|
||||
appId: string;
|
||||
versionName: string;
|
||||
time: Date;
|
||||
isPublish: boolean | undefined;
|
||||
tmbId: string;
|
||||
};
|
||||
|
||||
type Response = PaginationResponse<versionListResponse>;
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse<any>): Promise<Response> {
|
||||
const { current, pageSize, appId } = req.body as Props;
|
||||
|
||||
const [result, total] = await Promise.all([
|
||||
MongoAppVersion.find(
|
||||
{
|
||||
appId
|
||||
},
|
||||
'_id appId versionName time isPublish tmbId'
|
||||
)
|
||||
.sort({
|
||||
time: -1
|
||||
})
|
||||
.skip((current - 1) * pageSize)
|
||||
.limit(pageSize),
|
||||
MongoAppVersion.countDocuments({ appId })
|
||||
]);
|
||||
|
||||
const versionList = result.map((item) => {
|
||||
return {
|
||||
_id: item._id,
|
||||
appId: item.appId,
|
||||
versionName: item.versionName,
|
||||
time: item.time,
|
||||
isPublish: item.isPublish,
|
||||
tmbId: item.tmbId
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
total,
|
||||
list: versionList
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
@@ -29,6 +29,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { compareSnapshot } from '@/web/core/workflow/utils';
|
||||
import SaveAndPublishModal from '../WorkflowComponents/Flow/components/SaveAndPublish';
|
||||
import { formatTime2YMDHMS } from '@fastgpt/global/common/string/time';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const PublishHistories = dynamic(() => import('../WorkflowPublishHistoriesSlider'));
|
||||
|
||||
@@ -36,6 +37,7 @@ const Header = () => {
|
||||
const { t } = useTranslation();
|
||||
const { isPc } = useSystem();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
const { appDetail, onPublish, currentTab } = useContextSelector(AppContext, (v) => v);
|
||||
const isV2Workflow = appDetail?.version === 'v2';
|
||||
@@ -61,6 +63,9 @@ const Header = () => {
|
||||
} = useContextSelector(WorkflowContext, (v) => v);
|
||||
|
||||
const isPublished = useMemo(() => {
|
||||
/*
|
||||
Find the last saved snapshot in the past and future snapshots
|
||||
*/
|
||||
const savedSnapshot =
|
||||
future.findLast((snapshot) => snapshot.isSaved) || past.find((snapshot) => snapshot.isSaved);
|
||||
|
||||
@@ -97,9 +102,10 @@ const Header = () => {
|
||||
//@ts-ignore
|
||||
version: 'v2'
|
||||
});
|
||||
// Mark the current snapshot as saved
|
||||
setPast((prevPast) =>
|
||||
prevPast.map((item, index) =>
|
||||
index === prevPast.length - 1
|
||||
index === 0
|
||||
? {
|
||||
...item,
|
||||
isSaved: true
|
||||
@@ -171,6 +177,7 @@ const Header = () => {
|
||||
isLoading={loading}
|
||||
onClick={async () => {
|
||||
await onClickSave({});
|
||||
onClose();
|
||||
onBack();
|
||||
}}
|
||||
>
|
||||
@@ -246,7 +253,7 @@ const Header = () => {
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{({}) => (
|
||||
{({ onClose }) => (
|
||||
<MyBox p={1.5}>
|
||||
<MyBox
|
||||
display={'flex'}
|
||||
@@ -259,6 +266,10 @@ const Header = () => {
|
||||
isLoading={loading}
|
||||
onClick={async () => {
|
||||
await onClickSave({});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:saved_success')
|
||||
});
|
||||
}}
|
||||
>
|
||||
<MyIcon name={'core/workflow/upload'} w={'16px'} mr={2} />
|
||||
@@ -275,6 +286,7 @@ const Header = () => {
|
||||
if (data) {
|
||||
onSaveAndPublishModalOpen();
|
||||
}
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<MyIcon name={'core/workflow/publish'} w={'16px'} mr={2} />
|
||||
@@ -307,6 +319,8 @@ const Header = () => {
|
||||
isPc,
|
||||
currentTab,
|
||||
isPublished,
|
||||
onBack,
|
||||
onOpen,
|
||||
isOpen,
|
||||
onClose,
|
||||
t,
|
||||
@@ -314,8 +328,6 @@ const Header = () => {
|
||||
isV2Workflow,
|
||||
historiesDefaultData,
|
||||
isSave,
|
||||
onBack,
|
||||
onOpen,
|
||||
onClickSave,
|
||||
setHistoriesDefaultData,
|
||||
appDetail.chatConfig,
|
||||
@@ -323,6 +335,7 @@ const Header = () => {
|
||||
setWorkflowTestData,
|
||||
isSaveAndPublishModalOpen,
|
||||
onSaveAndPublishModalClose,
|
||||
toast,
|
||||
onSaveAndPublishModalOpen
|
||||
]);
|
||||
|
||||
|
@@ -113,7 +113,6 @@ const PublishHistoriesSlider = ({
|
||||
maxW={'300px'}
|
||||
px={0}
|
||||
showMask={false}
|
||||
top={'60px'}
|
||||
overflow={'unset'}
|
||||
>
|
||||
<Button
|
||||
|
@@ -21,6 +21,7 @@ import MyTag from '@fastgpt/web/components/common/Tag/index';
|
||||
import { publishStatusStyle } from '../constants';
|
||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const Header = ({
|
||||
appForm,
|
||||
@@ -32,6 +33,7 @@ const Header = ({
|
||||
const { t } = useTranslation();
|
||||
const { isPc } = useSystem();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const { appId, appDetail, onPublish, currentTab } = useContextSelector(AppContext, (v) => v);
|
||||
|
||||
const { data: paths = [] } = useRequest2(() => getAppFolderPath(appId), {
|
||||
@@ -75,8 +77,12 @@ const Header = ({
|
||||
chatConfig: data.chatConfig,
|
||||
type: AppTypeEnum.simple
|
||||
});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:publish_success')
|
||||
});
|
||||
},
|
||||
[onPublish, t]
|
||||
[onPublish, t, toast]
|
||||
);
|
||||
|
||||
const [historiesDefaultData, setHistoriesDefaultData] = useState<InitProps>();
|
||||
|
@@ -29,6 +29,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { compareSnapshot } from '@/web/core/workflow/utils';
|
||||
import SaveAndPublishModal from '../WorkflowComponents/Flow/components/SaveAndPublish';
|
||||
import { formatTime2YMDHMS } from '@fastgpt/global/common/string/time';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const PublishHistories = dynamic(() => import('../WorkflowPublishHistoriesSlider'));
|
||||
|
||||
@@ -36,6 +37,7 @@ const Header = () => {
|
||||
const { t } = useTranslation();
|
||||
const { isPc } = useSystem();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
const { appDetail, onPublish, currentTab } = useContextSelector(AppContext, (v) => v);
|
||||
const isV2Workflow = appDetail?.version === 'v2';
|
||||
@@ -103,7 +105,7 @@ const Header = () => {
|
||||
// Mark the current snapshot as saved
|
||||
setPast((prevPast) =>
|
||||
prevPast.map((item, index) =>
|
||||
index === prevPast.length - 1
|
||||
index === 0
|
||||
? {
|
||||
...item,
|
||||
isSaved: true
|
||||
@@ -175,6 +177,7 @@ const Header = () => {
|
||||
isLoading={loading}
|
||||
onClick={async () => {
|
||||
await onClickSave({});
|
||||
onClose();
|
||||
onBack();
|
||||
}}
|
||||
>
|
||||
@@ -250,7 +253,7 @@ const Header = () => {
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{({}) => (
|
||||
{({ onClose }) => (
|
||||
<MyBox p={1.5}>
|
||||
<MyBox
|
||||
display={'flex'}
|
||||
@@ -263,6 +266,10 @@ const Header = () => {
|
||||
isLoading={loading}
|
||||
onClick={async () => {
|
||||
await onClickSave({});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:saved_success')
|
||||
});
|
||||
}}
|
||||
>
|
||||
<MyIcon name={'core/workflow/upload'} w={'16px'} mr={2} />
|
||||
@@ -279,6 +286,7 @@ const Header = () => {
|
||||
if (data) {
|
||||
onSaveAndPublishModalOpen();
|
||||
}
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<MyIcon name={'core/workflow/publish'} w={'16px'} mr={2} />
|
||||
@@ -311,6 +319,8 @@ const Header = () => {
|
||||
isPc,
|
||||
currentTab,
|
||||
isPublished,
|
||||
onBack,
|
||||
onOpen,
|
||||
isOpen,
|
||||
onClose,
|
||||
t,
|
||||
@@ -318,8 +328,6 @@ const Header = () => {
|
||||
isV2Workflow,
|
||||
historiesDefaultData,
|
||||
isSave,
|
||||
onBack,
|
||||
onOpen,
|
||||
onClickSave,
|
||||
setHistoriesDefaultData,
|
||||
appDetail.chatConfig,
|
||||
@@ -327,6 +335,7 @@ const Header = () => {
|
||||
setWorkflowTestData,
|
||||
isSaveAndPublishModalOpen,
|
||||
onSaveAndPublishModalClose,
|
||||
toast,
|
||||
onSaveAndPublishModalOpen
|
||||
]);
|
||||
|
||||
|
@@ -17,7 +17,11 @@ const FlowController = React.memo(function FlowController() {
|
||||
|
||||
useEffect(() => {
|
||||
const keyDownHandler = (event: KeyboardEvent) => {
|
||||
if (event.key === 'z' && (event.ctrlKey || event.metaKey) && event.shiftKey) {
|
||||
if (
|
||||
(event.key === 'z' || event.key === 'Z') &&
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
event.shiftKey
|
||||
) {
|
||||
event.preventDefault();
|
||||
redo();
|
||||
} else if (event.key === 'z' && (event.ctrlKey || event.metaKey)) {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { Box, Button, Input, ModalBody, ModalFooter } from '@chakra-ui/react';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
type FormType = {
|
||||
@@ -17,6 +18,7 @@ const SaveAndPublishModal = ({
|
||||
onClickSave: (data: { isPublish: boolean; versionName: string }) => Promise<void>;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const { register, handleSubmit } = useForm<FormType>({
|
||||
defaultValues: {
|
||||
versionName: '',
|
||||
@@ -61,6 +63,10 @@ const SaveAndPublishModal = ({
|
||||
isLoading={isLoading}
|
||||
onClick={handleSubmit(async (data) => {
|
||||
await onClickSave({ ...data, isPublish: true });
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:publish_success')
|
||||
});
|
||||
onClose();
|
||||
})}
|
||||
>
|
||||
|
@@ -15,7 +15,7 @@ import { RuntimeEdgeItemType, StoreEdgeItemType } from '@fastgpt/global/core/wor
|
||||
import { FlowNodeChangeProps } from '@fastgpt/global/core/workflow/type/fe';
|
||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useLocalStorageState, useMemoizedFn, useUpdateEffect } from 'ahooks';
|
||||
import { useDebounceEffect, useLocalStorageState, useMemoizedFn, useUpdateEffect } from 'ahooks';
|
||||
import React, {
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
@@ -900,20 +900,23 @@ const WorkflowContextProvider = ({
|
||||
return true;
|
||||
},
|
||||
{
|
||||
debounceWait: 500,
|
||||
refreshDeps: [nodes, edges, appDetail.chatConfig, past]
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!nodes.length) return;
|
||||
saveSnapshot({
|
||||
pastNodes: nodes,
|
||||
pastEdges: edges,
|
||||
customTitle: formatTime2YMDHMS(new Date()),
|
||||
chatConfig: appDetail.chatConfig
|
||||
});
|
||||
}, [nodes, edges, appDetail.chatConfig]);
|
||||
useDebounceEffect(
|
||||
() => {
|
||||
if (!nodes.length) return;
|
||||
saveSnapshot({
|
||||
pastNodes: nodes,
|
||||
pastEdges: edges,
|
||||
customTitle: formatTime2YMDHMS(new Date()),
|
||||
chatConfig: appDetail.chatConfig
|
||||
});
|
||||
},
|
||||
[nodes, edges, appDetail.chatConfig],
|
||||
{ wait: 500 }
|
||||
);
|
||||
|
||||
const undo = useCallback(() => {
|
||||
if (past[1]) {
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import { getPublishList, updateAppVersion } from '@/web/core/app/api/version';
|
||||
import {
|
||||
getAppVersionDetail,
|
||||
getWorkflowVersionList,
|
||||
updateAppVersion
|
||||
} from '@/web/core/app/api/version';
|
||||
import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
|
||||
import CustomRightDrawer from '@fastgpt/web/components/common/MyDrawer/CustomRightDrawer';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -19,15 +23,18 @@ import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { versionListResponse } from '@/pages/api/core/app/version/listWorkflow';
|
||||
|
||||
const WorkflowPublishHistoriesSlider = ({ onClose }: { onClose: () => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const [currentTab, setCurrentTab] = useState<'myEdit' | 'teamCloud'>('myEdit');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<CustomRightDrawer
|
||||
onClose={() => onClose()}
|
||||
isLoading={isLoading}
|
||||
title={
|
||||
(
|
||||
<>
|
||||
@@ -49,10 +56,9 @@ const WorkflowPublishHistoriesSlider = ({ onClose }: { onClose: () => void }) =>
|
||||
maxW={'340px'}
|
||||
px={0}
|
||||
showMask={false}
|
||||
top={'60px'}
|
||||
overflow={'unset'}
|
||||
>
|
||||
{currentTab === 'myEdit' ? <MyEdit /> : <TeamCloud />}
|
||||
{currentTab === 'myEdit' ? <MyEdit /> : <TeamCloud setIsLoading={setIsLoading} />}
|
||||
</CustomRightDrawer>
|
||||
</>
|
||||
);
|
||||
@@ -163,14 +169,14 @@ const MyEdit = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const TeamCloud = () => {
|
||||
const TeamCloud = ({ setIsLoading }: { setIsLoading: (value: boolean) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const { appDetail } = useContextSelector(AppContext, (v) => v);
|
||||
const { saveSnapshot, resetSnapshot } = useContextSelector(WorkflowContext, (v) => v);
|
||||
const { loadAndGetTeamMembers } = useUserStore();
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const { list, ScrollList, isLoading, fetchData } = useScrollPagination(getPublishList, {
|
||||
const { list, ScrollList, isLoading, fetchData } = useScrollPagination(getWorkflowVersionList, {
|
||||
itemHeight: 40,
|
||||
overscan: 20,
|
||||
|
||||
@@ -188,6 +194,37 @@ const TeamCloud = () => {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const { toast } = useToast();
|
||||
|
||||
const onChangeVersion = async (versionItem: versionListResponse) => {
|
||||
setIsLoading(true);
|
||||
const versionDetail = await getAppVersionDetail(versionItem._id, versionItem.appId);
|
||||
setIsLoading(false);
|
||||
if (!versionDetail) return;
|
||||
const state = {
|
||||
nodes: versionDetail.nodes?.map((item) => storeNode2FlowNode({ item })),
|
||||
edges: versionDetail.edges?.map((item) => storeEdgesRenderEdge({ edge: item })),
|
||||
title: versionItem.versionName,
|
||||
chatConfig: versionDetail.chatConfig
|
||||
};
|
||||
|
||||
const res = await saveSnapshot({
|
||||
pastNodes: state.nodes,
|
||||
pastEdges: state.edges,
|
||||
chatConfig: state.chatConfig,
|
||||
customTitle: `${t('app:app.version_copy')}-${state.title}`
|
||||
});
|
||||
|
||||
if (!res) {
|
||||
return toast({
|
||||
title: t('workflow:workflow.Switch_failed'),
|
||||
status: 'warning'
|
||||
});
|
||||
}
|
||||
resetSnapshot(state);
|
||||
toast({
|
||||
title: t('workflow:workflow.Switch_success'),
|
||||
status: 'success'
|
||||
});
|
||||
};
|
||||
return (
|
||||
<ScrollList isLoading={isLoading} flex={'1 0 0'} px={5}>
|
||||
{list.map((data, index) => {
|
||||
@@ -209,28 +246,7 @@ const TeamCloud = () => {
|
||||
_hover={{
|
||||
bg: 'primary.50'
|
||||
}}
|
||||
onClick={async () => {
|
||||
const state = {
|
||||
nodes: item.nodes?.map((item) => storeNode2FlowNode({ item })),
|
||||
edges: item.edges?.map((item) => storeEdgesRenderEdge({ edge: item })),
|
||||
title: item.versionName,
|
||||
chatConfig: item.chatConfig
|
||||
};
|
||||
|
||||
const res = await saveSnapshot({
|
||||
pastNodes: state.nodes,
|
||||
pastEdges: state.edges,
|
||||
chatConfig: state.chatConfig,
|
||||
customTitle: `${t('app:app.version_copy')}-${state.title}`
|
||||
});
|
||||
|
||||
if (!res) return;
|
||||
resetSnapshot(state);
|
||||
toast({
|
||||
title: t('workflow:workflow.Switch_success'),
|
||||
status: 'success'
|
||||
});
|
||||
}}
|
||||
onClick={() => onChangeVersion(item)}
|
||||
>
|
||||
<MyPopover
|
||||
trigger="hover"
|
||||
@@ -308,6 +324,7 @@ const TeamCloud = () => {
|
||||
autoFocus
|
||||
h={8}
|
||||
defaultValue={item.versionName || formatTime2YMDHMS(item.time)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onBlur={async (e) => {
|
||||
setIsEditing(true);
|
||||
await updateAppVersion({
|
||||
|
@@ -84,7 +84,6 @@ export const AppContext = createContext<AppContextType>({
|
||||
|
||||
const AppContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
const { t } = useTranslation();
|
||||
const { appT } = useI18n();
|
||||
const router = useRouter();
|
||||
const { appId, currentTab = TabEnum.appEdit } = router.query as {
|
||||
appId: string;
|
||||
@@ -151,23 +150,18 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
}));
|
||||
});
|
||||
|
||||
const { runAsync: onPublish } = useRequest2(
|
||||
async (data: PostPublishAppProps) => {
|
||||
await postPublishApp(appId, data);
|
||||
setAppDetail((state) => ({
|
||||
...state,
|
||||
...data,
|
||||
modules: data.nodes || state.modules
|
||||
}));
|
||||
reloadAppLatestVersion();
|
||||
},
|
||||
{
|
||||
successToast: appT('publish_success')
|
||||
}
|
||||
);
|
||||
const { runAsync: onPublish } = useRequest2(async (data: PostPublishAppProps) => {
|
||||
await postPublishApp(appId, data);
|
||||
setAppDetail((state) => ({
|
||||
...state,
|
||||
...data,
|
||||
modules: data.nodes || state.modules
|
||||
}));
|
||||
reloadAppLatestVersion();
|
||||
});
|
||||
|
||||
const { openConfirm: openConfirmDel, ConfirmModal: ConfirmDelModal } = useConfirm({
|
||||
content: appT('confirm_del_app_tip'),
|
||||
content: t('app:confirm_del_app_tip'),
|
||||
type: 'delete'
|
||||
});
|
||||
const { runAsync: deleteApp } = useRequest2(
|
||||
|
@@ -7,6 +7,7 @@ import type {
|
||||
getLatestVersionResponse
|
||||
} from '@/pages/api/core/app/version/latest';
|
||||
import { UpdateAppVersionBody } from '@/pages/api/core/app/version/update';
|
||||
import { versionListResponse } from '@/pages/api/core/app/version/listWorkflow';
|
||||
|
||||
export const getAppLatestVersion = (data: getLatestVersionQuery) =>
|
||||
GET<getLatestVersionResponse>('/core/app/version/latest', data);
|
||||
@@ -17,6 +18,12 @@ export const postPublishApp = (appId: string, data: PostPublishAppProps) =>
|
||||
export const getPublishList = (data: PaginationProps<{ appId: string }>) =>
|
||||
POST<PaginationResponse<AppVersionSchemaType>>('/core/app/version/list', data);
|
||||
|
||||
export const getWorkflowVersionList = (data: PaginationProps<{ appId: string }>) =>
|
||||
POST<PaginationResponse<versionListResponse>>('/core/app/version/listWorkflow', data);
|
||||
|
||||
export const getAppVersionDetail = (versionId: string, appId: string) =>
|
||||
GET<AppVersionSchemaType>(`/core/app/version/detail?versionId=${versionId}&appId=${appId}`);
|
||||
|
||||
export const postRevertVersion = (appId: string, data: PostRevertAppProps) =>
|
||||
POST(`/core/app/version/revert?appId=${appId}`, data);
|
||||
|
||||
|
Reference in New Issue
Block a user