Commit 9d5a8777 by DigHuang Committed by GitHub

refactor(skill): optimize publish flow & upgrade sandbox images (#7132)

parent e24fef92
...@@ -237,7 +237,7 @@ services: ...@@ -237,7 +237,7 @@ services:
retries: 3 retries: 3
fastgpt-agent-sandbox-proxy: fastgpt-agent-sandbox-proxy:
container_name: fastgpt-agent-sandbox-proxy container_name: fastgpt-agent-sandbox-proxy
image: ghcr.io/labring/fastgpt-agent-sandbox-proxy:v0.2.0-beta1 image: ghcr.io/labring/fastgpt-agent-sandbox-proxy:v0.2.0-beta2
ports: ports:
- 1006:1006 - 1006:1006
networks: networks:
...@@ -318,7 +318,7 @@ services: ...@@ -318,7 +318,7 @@ services:
retries: 5 retries: 5
# Pre-pull only: not started by `docker compose up` (uses profile `prepull`). # Pre-pull only: not started by `docker compose up` (uses profile `prepull`).
opensandbox-agent-sandbox-image: opensandbox-agent-sandbox-image:
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-agent-sandbox:v0.2.0-beta1 image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-agent-sandbox:v0.2.0-beta2
profiles: profiles:
- prepull - prepull
opensandbox-execd-image: opensandbox-execd-image:
......
...@@ -237,7 +237,7 @@ services: ...@@ -237,7 +237,7 @@ services:
retries: 3 retries: 3
fastgpt-agent-sandbox-proxy: fastgpt-agent-sandbox-proxy:
container_name: fastgpt-agent-sandbox-proxy container_name: fastgpt-agent-sandbox-proxy
image: ghcr.io/labring/fastgpt-agent-sandbox-proxy:v0.2.0-beta1 image: ghcr.io/labring/fastgpt-agent-sandbox-proxy:v0.2.0-beta2
ports: ports:
- 1006:1006 - 1006:1006
networks: networks:
...@@ -318,7 +318,7 @@ services: ...@@ -318,7 +318,7 @@ services:
retries: 5 retries: 5
# Pre-pull only: not started by `docker compose up` (uses profile `prepull`). # Pre-pull only: not started by `docker compose up` (uses profile `prepull`).
opensandbox-agent-sandbox-image: opensandbox-agent-sandbox-image:
image: ghcr.io/labring/fastgpt-agent-sandbox:v0.2.0-beta1 image: ghcr.io/labring/fastgpt-agent-sandbox:v0.2.0-beta2
profiles: profiles:
- prepull - prepull
opensandbox-execd-image: opensandbox-execd-image:
......
...@@ -218,17 +218,6 @@ const EditorContent = ({ ...@@ -218,17 +218,6 @@ const EditorContent = ({
}); });
} }
); );
// 失去焦点时自动保存脏文件
editor.onDidBlurEditorText(() => {
if (!canWrite) return;
const files = openedFilesRef.current;
if (!files) return;
const currentFile = files.find((f) => f.path === activeFilePath);
if (currentFile?.isDirty) {
saveFile(activeFilePath);
}
});
}} }}
onChange={(value) => { onChange={(value) => {
if (!canWrite) return; if (!canWrite) return;
......
...@@ -941,7 +941,7 @@ export const useSandboxFileStore = ({ ...@@ -941,7 +941,7 @@ export const useSandboxFileStore = ({
} }
}, [canWrite, openedFilesRef, rpcCall, toast, t]); }, [canWrite, openedFilesRef, rpcCall, toast, t]);
// 1.5 秒防抖自动保存脏文件 // 500ms 防抖自动保存脏文件
useEffect(() => { useEffect(() => {
const dirtyFiles = openedFiles.filter((f) => f.isDirty && !f.isBinary && !f.isUnknown); const dirtyFiles = openedFiles.filter((f) => f.isDirty && !f.isBinary && !f.isUnknown);
if (dirtyFiles.length === 0) return; if (dirtyFiles.length === 0) return;
...@@ -950,7 +950,7 @@ export const useSandboxFileStore = ({ ...@@ -950,7 +950,7 @@ export const useSandboxFileStore = ({
dirtyFiles.forEach((f) => { dirtyFiles.forEach((f) => {
saveFile(f.path); saveFile(f.path);
}); });
}, 1500); }, 500);
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [openedFiles, saveFile]); }, [openedFiles, saveFile]);
......
...@@ -29,7 +29,7 @@ const Content = () => { ...@@ -29,7 +29,7 @@ const Content = () => {
pt={'16px'} pt={'16px'}
pb={'16px'} pb={'16px'}
pr={'16px'} pr={'16px'}
pl={'8px'} pl={0}
> >
{sandboxState === 'failed' ? ( {sandboxState === 'failed' ? (
<SandboxError /> <SandboxError />
......
...@@ -36,8 +36,6 @@ const EditResourceModal = dynamic(() => import('@/components/common/Modal/EditRe ...@@ -36,8 +36,6 @@ const EditResourceModal = dynamic(() => import('@/components/common/Modal/EditRe
const ConfigPerModal = dynamic(() => import('@/components/support/permission/ConfigPerModal')); const ConfigPerModal = dynamic(() => import('@/components/support/permission/ConfigPerModal'));
export const HeaderContext = createContext<{ export const HeaderContext = createContext<{
savingAll: boolean;
setSavingAll: React.Dispatch<React.SetStateAction<boolean>>;
editedSkill: EditResourceInfoFormType | undefined; editedSkill: EditResourceInfoFormType | undefined;
setEditedSkill: React.Dispatch<React.SetStateAction<EditResourceInfoFormType | undefined>>; setEditedSkill: React.Dispatch<React.SetStateAction<EditResourceInfoFormType | undefined>>;
showPermModal: boolean; showPermModal: boolean;
...@@ -55,19 +53,15 @@ export const HeaderContext = createContext<{ ...@@ -55,19 +53,15 @@ export const HeaderContext = createContext<{
) => Promise<any>; ) => Promise<any>;
onExportSkill: (skillId: string, skillName: string) => Promise<any>; onExportSkill: (skillId: string, skillName: string) => Promise<any>;
onSaveDeploy: (props: { skillId: string; versionName: string }) => Promise<any>; onSaveDeploy: (props: { skillId: string; versionName: string }) => Promise<any>;
handlePublishClick: () => Promise<void>; handlePublishClick: () => void;
} | null>(null); } | null>(null);
export const HeaderProvider = ({ children }: { children: React.ReactNode }) => { export const HeaderProvider = ({ children }: { children: React.ReactNode }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter(); const router = useRouter();
const { refreshSkillDetail, saveAllRef } = useContextSelector(SkillDetailContext, (v) => ({ const refreshSkillDetail = useContextSelector(SkillDetailContext, (v) => v.refreshSkillDetail);
refreshSkillDetail: v.refreshSkillDetail,
saveAllRef: v.saveAllRef
}));
const [savingAll, setSavingAll] = useState(false);
const [editedSkill, setEditedSkill] = useState<EditResourceInfoFormType>(); const [editedSkill, setEditedSkill] = useState<EditResourceInfoFormType>();
const [showPermModal, setShowPermModal] = useState(false); const [showPermModal, setShowPermModal] = useState(false);
...@@ -128,25 +122,13 @@ export const HeaderProvider = ({ children }: { children: React.ReactNode }) => { ...@@ -128,25 +122,13 @@ export const HeaderProvider = ({ children }: { children: React.ReactNode }) => {
onClose: onClosePublishModal onClose: onClosePublishModal
} = useDisclosure(); } = useDisclosure();
const handlePublishClick = async () => { const handlePublishClick = () => {
try { onOpenPublishModal();
setSavingAll(true);
if (saveAllRef && saveAllRef.current) {
await saveAllRef.current();
}
onOpenPublishModal();
} catch (error) {
console.error('Save all before publish failed:', error);
} finally {
setSavingAll(false);
}
}; };
return ( return (
<HeaderContext.Provider <HeaderContext.Provider
value={{ value={{
savingAll,
setSavingAll,
editedSkill, editedSkill,
setEditedSkill, setEditedSkill,
showPermModal, showPermModal,
...@@ -279,7 +261,7 @@ export const LeftHeader = () => { ...@@ -279,7 +261,7 @@ export const LeftHeader = () => {
justifyContent={'space-between'} justifyContent={'space-between'}
gap={'8px'} gap={'8px'}
pl={'24px'} pl={'24px'}
pr={0} pr={'8px'}
bg={'transparent'} bg={'transparent'}
userSelect={'none'} userSelect={'none'}
> >
...@@ -351,7 +333,7 @@ export const LeftHeader = () => { ...@@ -351,7 +333,7 @@ export const LeftHeader = () => {
export const RightHeader = () => { export const RightHeader = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { handlePublishClick, isSaving, savingAll } = useHeader(); const { handlePublishClick, isSaving } = useHeader();
return ( return (
<SkillHistoriesPopover <SkillHistoriesPopover
...@@ -361,7 +343,7 @@ export const RightHeader = () => { ...@@ -361,7 +343,7 @@ export const RightHeader = () => {
h={'34px'} h={'34px'}
px={'14px'} px={'14px'}
variant={'primary'} variant={'primary'}
isLoading={isSaving || savingAll} isLoading={isSaving}
onClick={handlePublishClick} onClick={handlePublishClick}
> >
{t('common:Publish')} {t('common:Publish')}
...@@ -373,10 +355,15 @@ export const RightHeader = () => { ...@@ -373,10 +355,15 @@ export const RightHeader = () => {
export const HeaderDialogs = () => { export const HeaderDialogs = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { skillDetail, refreshSkillDetail } = useContextSelector(SkillDetailContext, (v) => ({ const { skillDetail, refreshSkillDetail, saveAllRef } = useContextSelector(
skillDetail: v.skillDetail, SkillDetailContext,
refreshSkillDetail: v.refreshSkillDetail (v) => ({
})); skillDetail: v.skillDetail,
refreshSkillDetail: v.refreshSkillDetail,
saveAllRef: v.saveAllRef
})
);
const [isConfirmingPublish, setIsConfirmingPublish] = useState(false);
const { const {
editedSkill, editedSkill,
...@@ -399,11 +386,17 @@ export const HeaderDialogs = () => { ...@@ -399,11 +386,17 @@ export const HeaderDialogs = () => {
{isPublishModalOpen && ( {isPublishModalOpen && (
<SaveAndPublishModal <SaveAndPublishModal
title={t('common:Publish')} title={t('common:Publish')}
isLoading={isSaving} isLoading={isSaving || isConfirmingPublish}
onClose={onPublishModalClose} onClose={onPublishModalClose}
onConfirm={async (versionName) => { onConfirm={async (versionName) => {
await onSaveDeploy({ skillId: skillDetail._id, versionName }); try {
onPublishModalClose(); setIsConfirmingPublish(true);
await saveAllRef.current?.();
await onSaveDeploy({ skillId: skillDetail._id, versionName });
onPublishModalClose();
} finally {
setIsConfirmingPublish(false);
}
}} }}
/> />
)} )}
......
...@@ -110,8 +110,8 @@ export const useSkillChatTest = ({ ...@@ -110,8 +110,8 @@ export const useSkillChatTest = ({
pl={'16px'} pl={'16px'}
pr={0} pr={0}
maxW={'100%'} maxW={'100%'}
boxBodyProps={{ px: 0, maxW: '100%', mx: 0 }} boxBodyProps={{ px: 0, pr: '8px', maxW: '100%', mx: 0 }}
inputBodyProps={{ maxW: '100%', mx: 0, px: 0, pl: 0, pr: 0 }} inputBodyProps={{ maxW: '100%', mx: 0, px: 0, pl: 0, pr: '8px' }}
EmptyState={ EmptyState={
<Flex <Flex
flex={1} flex={1}
......
...@@ -21,7 +21,7 @@ const MainLayout = () => { ...@@ -21,7 +21,7 @@ const MainLayout = () => {
return ( return (
<HeaderProvider> <HeaderProvider>
<Flex h={'100%'} bg={'myGray.25'} overflow={'hidden'} gap={'8px'}> <Flex h={'100%'} bg={'myGray.25'} overflow={'hidden'}>
{/* 左栏: 488px 预览对话区域 */} {/* 左栏: 488px 预览对话区域 */}
<Flex <Flex
w={'488px'} w={'488px'}
......
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 sign in to comment