perf: onpublish app (#2498)
This commit is contained in:
parent
fa106eb24c
commit
ad63210f45
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Flex,
|
Flex,
|
||||||
@ -39,14 +39,20 @@ const Header = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const { appDetail, onPublish, currentTab } = useContextSelector(AppContext, (v) => v);
|
const { appDetail, onSaveApp, currentTab } = useContextSelector(AppContext, (v) => v);
|
||||||
const isV2Workflow = appDetail?.version === 'v2';
|
const isV2Workflow = appDetail?.version === 'v2';
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
||||||
|
const {
|
||||||
|
isOpen: isOpenBackConfirm,
|
||||||
|
onOpen: onOpenBackConfirm,
|
||||||
|
onClose: onCloseBackConfirm
|
||||||
|
} = useDisclosure();
|
||||||
const {
|
const {
|
||||||
isOpen: isSaveAndPublishModalOpen,
|
isOpen: isSaveAndPublishModalOpen,
|
||||||
onOpen: onSaveAndPublishModalOpen,
|
onOpen: onSaveAndPublishModalOpen,
|
||||||
onClose: onSaveAndPublishModalClose
|
onClose: onSaveAndPublishModalClose
|
||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
|
||||||
const [isSave, setIsSave] = useState(false);
|
const [isSave, setIsSave] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -94,7 +100,7 @@ const Header = () => {
|
|||||||
const data = flowData2StoreData();
|
const data = flowData2StoreData();
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
await onPublish({
|
await onSaveApp({
|
||||||
...data,
|
...data,
|
||||||
isPublish,
|
isPublish,
|
||||||
versionName,
|
versionName,
|
||||||
@ -157,34 +163,9 @@ const Header = () => {
|
|||||||
name={'common/leftArrowLight'}
|
name={'common/leftArrowLight'}
|
||||||
w={'1.75rem'}
|
w={'1.75rem'}
|
||||||
cursor={'pointer'}
|
cursor={'pointer'}
|
||||||
onClick={isPublished ? onBack : onOpen}
|
onClick={isPublished ? onBack : onOpenBackConfirm}
|
||||||
/>
|
/>
|
||||||
<MyModal
|
|
||||||
isOpen={isOpen}
|
|
||||||
onClose={onClose}
|
|
||||||
iconSrc="common/warn"
|
|
||||||
title={t('common:common.Exit')}
|
|
||||||
w={'400px'}
|
|
||||||
>
|
|
||||||
<ModalBody>
|
|
||||||
<Box>{t('workflow:workflow.exit_tips')}</Box>
|
|
||||||
</ModalBody>
|
|
||||||
<ModalFooter gap={3}>
|
|
||||||
<Button variant={'whiteDanger'} onClick={onBack}>
|
|
||||||
{t('common:common.Exit Directly')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
isLoading={loading}
|
|
||||||
onClick={async () => {
|
|
||||||
await onClickSave({});
|
|
||||||
onClose();
|
|
||||||
onBack();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('common:common.Save_and_exit')}
|
|
||||||
</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</MyModal>
|
|
||||||
{/* app info */}
|
{/* app info */}
|
||||||
<Box ml={1}>
|
<Box ml={1}>
|
||||||
<AppCard isPublished={isPublished} showSaveStatus={isV2Workflow} />
|
<AppCard isPublished={isPublished} showSaveStatus={isV2Workflow} />
|
||||||
@ -313,6 +294,32 @@ const Header = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<MyModal
|
||||||
|
isOpen={isOpenBackConfirm}
|
||||||
|
onClose={onCloseBackConfirm}
|
||||||
|
iconSrc="common/warn"
|
||||||
|
title={t('common:common.Exit')}
|
||||||
|
w={'400px'}
|
||||||
|
>
|
||||||
|
<ModalBody>
|
||||||
|
<Box>{t('workflow:workflow.exit_tips')}</Box>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter gap={3}>
|
||||||
|
<Button variant={'whiteDanger'} onClick={onBack}>
|
||||||
|
{t('common:common.Exit Directly')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
isLoading={loading}
|
||||||
|
onClick={async () => {
|
||||||
|
await onClickSave({});
|
||||||
|
onCloseBackConfirm();
|
||||||
|
onBack();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('common:common.Save_and_exit')}
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</MyModal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
@ -320,9 +327,9 @@ const Header = () => {
|
|||||||
currentTab,
|
currentTab,
|
||||||
isPublished,
|
isPublished,
|
||||||
onBack,
|
onBack,
|
||||||
onOpen,
|
isOpenBackConfirm,
|
||||||
isOpen,
|
onOpenBackConfirm,
|
||||||
onClose,
|
onCloseBackConfirm,
|
||||||
t,
|
t,
|
||||||
loading,
|
loading,
|
||||||
isV2Workflow,
|
isV2Workflow,
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import { publishStatusStyle } from '../constants';
|
|||||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
|
import { formatTime2YMDHMS } from '@fastgpt/global/common/string/time';
|
||||||
|
|
||||||
const Header = ({
|
const Header = ({
|
||||||
appForm,
|
appForm,
|
||||||
@ -34,7 +35,7 @@ const Header = ({
|
|||||||
const { isPc } = useSystem();
|
const { isPc } = useSystem();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { appId, appDetail, onPublish, currentTab } = useContextSelector(AppContext, (v) => v);
|
const { appId, appDetail, onSaveApp, currentTab } = useContextSelector(AppContext, (v) => v);
|
||||||
|
|
||||||
const { data: paths = [] } = useRequest2(() => getAppFolderPath(appId), {
|
const { data: paths = [] } = useRequest2(() => getAppFolderPath(appId), {
|
||||||
manual: false,
|
manual: false,
|
||||||
@ -71,18 +72,20 @@ const Header = ({
|
|||||||
const onSubmitPublish = useCallback(
|
const onSubmitPublish = useCallback(
|
||||||
async (data: AppSimpleEditFormType) => {
|
async (data: AppSimpleEditFormType) => {
|
||||||
const { nodes, edges } = form2AppWorkflow(data, t);
|
const { nodes, edges } = form2AppWorkflow(data, t);
|
||||||
await onPublish({
|
await onSaveApp({
|
||||||
nodes,
|
nodes,
|
||||||
edges,
|
edges,
|
||||||
chatConfig: data.chatConfig,
|
chatConfig: data.chatConfig,
|
||||||
type: AppTypeEnum.simple
|
type: AppTypeEnum.simple,
|
||||||
|
isPublish: true,
|
||||||
|
versionName: formatTime2YMDHMS(new Date())
|
||||||
});
|
});
|
||||||
toast({
|
toast({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
title: t('app:publish_success')
|
title: t('app:publish_success')
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[onPublish, t, toast]
|
[onSaveApp, t, toast]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [historiesDefaultData, setHistoriesDefaultData] = useState<InitProps>();
|
const [historiesDefaultData, setHistoriesDefaultData] = useState<InitProps>();
|
||||||
|
|||||||
@ -39,9 +39,13 @@ const Header = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const { appDetail, onPublish, currentTab } = useContextSelector(AppContext, (v) => v);
|
const { appDetail, onSaveApp, currentTab } = useContextSelector(AppContext, (v) => v);
|
||||||
const isV2Workflow = appDetail?.version === 'v2';
|
const isV2Workflow = appDetail?.version === 'v2';
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const {
|
||||||
|
isOpen: isOpenBackConfirm,
|
||||||
|
onOpen: onOpenBackConfirm,
|
||||||
|
onClose: onCloseBackConfirm
|
||||||
|
} = useDisclosure();
|
||||||
const {
|
const {
|
||||||
isOpen: isSaveAndPublishModalOpen,
|
isOpen: isSaveAndPublishModalOpen,
|
||||||
onOpen: onSaveAndPublishModalOpen,
|
onOpen: onSaveAndPublishModalOpen,
|
||||||
@ -94,7 +98,7 @@ const Header = () => {
|
|||||||
const data = flowData2StoreData();
|
const data = flowData2StoreData();
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
await onPublish({
|
await onSaveApp({
|
||||||
...data,
|
...data,
|
||||||
isPublish,
|
isPublish,
|
||||||
versionName,
|
versionName,
|
||||||
@ -157,34 +161,9 @@ const Header = () => {
|
|||||||
name={'common/leftArrowLight'}
|
name={'common/leftArrowLight'}
|
||||||
w={'1.75rem'}
|
w={'1.75rem'}
|
||||||
cursor={'pointer'}
|
cursor={'pointer'}
|
||||||
onClick={isPublished ? onBack : onOpen}
|
onClick={isPublished ? onBack : onOpenBackConfirm}
|
||||||
/>
|
/>
|
||||||
<MyModal
|
|
||||||
isOpen={isOpen}
|
|
||||||
onClose={onClose}
|
|
||||||
iconSrc="common/warn"
|
|
||||||
title={t('common:common.Exit')}
|
|
||||||
w={'400px'}
|
|
||||||
>
|
|
||||||
<ModalBody>
|
|
||||||
<Box>{t('workflow:workflow.exit_tips')}</Box>
|
|
||||||
</ModalBody>
|
|
||||||
<ModalFooter gap={3}>
|
|
||||||
<Button variant={'whiteDanger'} onClick={onBack}>
|
|
||||||
{t('common:common.Exit Directly')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
isLoading={loading}
|
|
||||||
onClick={async () => {
|
|
||||||
await onClickSave({});
|
|
||||||
onClose();
|
|
||||||
onBack();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('common:common.Save_and_exit')}
|
|
||||||
</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</MyModal>
|
|
||||||
{/* app info */}
|
{/* app info */}
|
||||||
<Box ml={1}>
|
<Box ml={1}>
|
||||||
<AppCard isPublished={isPublished} showSaveStatus={isV2Workflow} />
|
<AppCard isPublished={isPublished} showSaveStatus={isV2Workflow} />
|
||||||
@ -313,6 +292,36 @@ const Header = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<MyModal
|
||||||
|
isOpen={isOpenBackConfirm}
|
||||||
|
onClose={onCloseBackConfirm}
|
||||||
|
iconSrc="common/warn"
|
||||||
|
title={t('common:common.Exit')}
|
||||||
|
w={'400px'}
|
||||||
|
>
|
||||||
|
<ModalBody>
|
||||||
|
<Box>{t('workflow:workflow.exit_tips')}</Box>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter gap={3}>
|
||||||
|
<Button variant={'whiteDanger'} onClick={onBack}>
|
||||||
|
{t('common:common.Exit Directly')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
isLoading={loading}
|
||||||
|
onClick={async () => {
|
||||||
|
await onClickSave({});
|
||||||
|
onCloseBackConfirm();
|
||||||
|
onBack();
|
||||||
|
toast({
|
||||||
|
status: 'success',
|
||||||
|
title: t('app:saved_success')
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('common:common.Save_and_exit')}
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</MyModal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
@ -320,9 +329,9 @@ const Header = () => {
|
|||||||
currentTab,
|
currentTab,
|
||||||
isPublished,
|
isPublished,
|
||||||
onBack,
|
onBack,
|
||||||
onOpen,
|
isOpenBackConfirm,
|
||||||
isOpen,
|
onOpenBackConfirm,
|
||||||
onClose,
|
onCloseBackConfirm,
|
||||||
t,
|
t,
|
||||||
loading,
|
loading,
|
||||||
isV2Workflow,
|
isV2Workflow,
|
||||||
|
|||||||
@ -28,13 +28,11 @@ import { versionListResponse } from '@/pages/api/core/app/version/listWorkflow';
|
|||||||
const WorkflowPublishHistoriesSlider = ({ onClose }: { onClose: () => void }) => {
|
const WorkflowPublishHistoriesSlider = ({ onClose }: { onClose: () => void }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [currentTab, setCurrentTab] = useState<'myEdit' | 'teamCloud'>('myEdit');
|
const [currentTab, setCurrentTab] = useState<'myEdit' | 'teamCloud'>('myEdit');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CustomRightDrawer
|
<CustomRightDrawer
|
||||||
onClose={() => onClose()}
|
onClose={() => onClose()}
|
||||||
isLoading={isLoading}
|
|
||||||
title={
|
title={
|
||||||
(
|
(
|
||||||
<>
|
<>
|
||||||
@ -58,7 +56,7 @@ const WorkflowPublishHistoriesSlider = ({ onClose }: { onClose: () => void }) =>
|
|||||||
showMask={false}
|
showMask={false}
|
||||||
overflow={'unset'}
|
overflow={'unset'}
|
||||||
>
|
>
|
||||||
{currentTab === 'myEdit' ? <MyEdit /> : <TeamCloud setIsLoading={setIsLoading} />}
|
{currentTab === 'myEdit' ? <MyEdit /> : <TeamCloud />}
|
||||||
</CustomRightDrawer>
|
</CustomRightDrawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -81,14 +79,17 @@ const MyEdit = () => {
|
|||||||
h={'30px'}
|
h={'30px'}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const initialSnapshot = past[past.length - 1];
|
const initialSnapshot = past[past.length - 1];
|
||||||
|
|
||||||
const res = await saveSnapshot({
|
const res = await saveSnapshot({
|
||||||
pastNodes: initialSnapshot.nodes,
|
pastNodes: initialSnapshot.nodes,
|
||||||
pastEdges: initialSnapshot.edges,
|
pastEdges: initialSnapshot.edges,
|
||||||
chatConfig: initialSnapshot.chatConfig,
|
chatConfig: initialSnapshot.chatConfig,
|
||||||
customTitle: t(`app:app.version_initial_copy`)
|
customTitle: t(`app:app.version_initial_copy`)
|
||||||
});
|
});
|
||||||
if (!res) return;
|
if (res) {
|
||||||
resetSnapshot(initialSnapshot);
|
resetSnapshot(initialSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t('workflow:workflow.Switch_success'),
|
title: t('workflow:workflow.Switch_success'),
|
||||||
status: 'success'
|
status: 'success'
|
||||||
@ -120,8 +121,9 @@ const MyEdit = () => {
|
|||||||
chatConfig: item.chatConfig,
|
chatConfig: item.chatConfig,
|
||||||
customTitle: `${t('app:app.version_copy')}-${item.title}`
|
customTitle: `${t('app:app.version_copy')}-${item.title}`
|
||||||
});
|
});
|
||||||
if (!res) return;
|
if (res) {
|
||||||
resetSnapshot(item);
|
resetSnapshot(item);
|
||||||
|
}
|
||||||
toast({
|
toast({
|
||||||
title: t('workflow:workflow.Switch_success'),
|
title: t('workflow:workflow.Switch_success'),
|
||||||
status: 'success'
|
status: 'success'
|
||||||
@ -169,7 +171,7 @@ const MyEdit = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TeamCloud = ({ setIsLoading }: { setIsLoading: (value: boolean) => void }) => {
|
const TeamCloud = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { appDetail } = useContextSelector(AppContext, (v) => v);
|
const { appDetail } = useContextSelector(AppContext, (v) => v);
|
||||||
const { saveSnapshot, resetSnapshot } = useContextSelector(WorkflowContext, (v) => v);
|
const { saveSnapshot, resetSnapshot } = useContextSelector(WorkflowContext, (v) => v);
|
||||||
@ -194,11 +196,12 @@ const TeamCloud = ({ setIsLoading }: { setIsLoading: (value: boolean) => void })
|
|||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const onChangeVersion = async (versionItem: versionListResponse) => {
|
const { runAsync: onChangeVersion, loading: isLoadingVersion } = useRequest2(
|
||||||
setIsLoading(true);
|
async (versionItem: versionListResponse) => {
|
||||||
const versionDetail = await getAppVersionDetail(versionItem._id, versionItem.appId);
|
const versionDetail = await getAppVersionDetail(versionItem._id, versionItem.appId);
|
||||||
setIsLoading(false);
|
|
||||||
if (!versionDetail) return;
|
if (!versionDetail) return;
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
nodes: versionDetail.nodes?.map((item) => storeNode2FlowNode({ item })),
|
nodes: versionDetail.nodes?.map((item) => storeNode2FlowNode({ item })),
|
||||||
edges: versionDetail.edges?.map((item) => storeEdgesRenderEdge({ edge: item })),
|
edges: versionDetail.edges?.map((item) => storeEdgesRenderEdge({ edge: item })),
|
||||||
@ -206,27 +209,23 @@ const TeamCloud = ({ setIsLoading }: { setIsLoading: (value: boolean) => void })
|
|||||||
chatConfig: versionDetail.chatConfig
|
chatConfig: versionDetail.chatConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await saveSnapshot({
|
await saveSnapshot({
|
||||||
pastNodes: state.nodes,
|
pastNodes: state.nodes,
|
||||||
pastEdges: state.edges,
|
pastEdges: state.edges,
|
||||||
chatConfig: state.chatConfig,
|
chatConfig: state.chatConfig,
|
||||||
customTitle: `${t('app:app.version_copy')}-${state.title}`
|
customTitle: `${t('app:app.version_copy')}-${state.title}`
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
return toast({
|
|
||||||
title: t('workflow:workflow.Switch_failed'),
|
|
||||||
status: 'warning'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resetSnapshot(state);
|
resetSnapshot(state);
|
||||||
toast({
|
toast({
|
||||||
title: t('workflow:workflow.Switch_success'),
|
title: t('workflow:workflow.Switch_success'),
|
||||||
status: 'success'
|
status: 'success'
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollList isLoading={isLoading} flex={'1 0 0'} px={5}>
|
<ScrollList isLoading={isLoading || isLoadingVersion} flex={'1 0 0'} px={5}>
|
||||||
{list.map((data, index) => {
|
{list.map((data, index) => {
|
||||||
const item = data.data;
|
const item = data.data;
|
||||||
const firstPublishedIndex = list.findIndex((data) => data.data.isPublish);
|
const firstPublishedIndex = list.findIndex((data) => data.data.isPublish);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ type AppContextType = {
|
|||||||
onOpenInfoEdit: () => void;
|
onOpenInfoEdit: () => void;
|
||||||
onOpenTeamTagModal: () => void;
|
onOpenTeamTagModal: () => void;
|
||||||
onDelApp: () => void;
|
onDelApp: () => void;
|
||||||
onPublish: (data: PostPublishAppProps) => Promise<void>;
|
onSaveApp: (data: PostPublishAppProps) => Promise<void>;
|
||||||
appLatestVersion:
|
appLatestVersion:
|
||||||
| {
|
| {
|
||||||
nodes: StoreNodeItemType[];
|
nodes: StoreNodeItemType[];
|
||||||
@ -70,7 +70,7 @@ export const AppContext = createContext<AppContextType>({
|
|||||||
onDelApp: function (): void {
|
onDelApp: function (): void {
|
||||||
throw new Error('Function not implemented.');
|
throw new Error('Function not implemented.');
|
||||||
},
|
},
|
||||||
onPublish: function (data: PostPublishAppProps): Promise<void> {
|
onSaveApp: function (data: PostPublishAppProps): Promise<void> {
|
||||||
throw new Error('Function not implemented.');
|
throw new Error('Function not implemented.');
|
||||||
},
|
},
|
||||||
appLatestVersion: undefined,
|
appLatestVersion: undefined,
|
||||||
@ -150,7 +150,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
const { runAsync: onPublish } = useRequest2(async (data: PostPublishAppProps) => {
|
const { runAsync: onSaveApp } = useRequest2(async (data: PostPublishAppProps) => {
|
||||||
await postPublishApp(appId, data);
|
await postPublishApp(appId, data);
|
||||||
setAppDetail((state) => ({
|
setAppDetail((state) => ({
|
||||||
...state,
|
...state,
|
||||||
@ -190,7 +190,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
onOpenInfoEdit,
|
onOpenInfoEdit,
|
||||||
onOpenTeamTagModal,
|
onOpenTeamTagModal,
|
||||||
onDelApp,
|
onDelApp,
|
||||||
onPublish,
|
onSaveApp,
|
||||||
appLatestVersion,
|
appLatestVersion,
|
||||||
reloadAppLatestVersion,
|
reloadAppLatestVersion,
|
||||||
reloadApp
|
reloadApp
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user