const MyApps = () => {
const { t } = useTranslation();
const { appT } = useI18n();
const router = useRouter();
const { isPc } = useSystem();
const {
paths,
parentId,
myApps,
appType,
loadMyApps,
onUpdateApp,
setMoveAppId,
isFetchingApps,
folderDetail,
refetchFolderDetail,
searchKey,
setSearchKey
} = useContextSelector(AppListContext, (v) => v);
const { userInfo } = useUserStore();
const [createAppType, setCreateAppType] = useState<CreateAppType>();
const {
isOpen: isOpenCreateHttpPlugin,
onOpen: onOpenCreateHttpPlugin,
onClose: onCloseCreateHttpPlugin
} = useDisclosure();
const [editFolder, setEditFolder] = useState<EditFolderFormType>();
const [templateModalType, setTemplateModalType] = useState<AppTypeEnum | 'all'>();
const { runAsync: onCreateFolder } = useRequest2(postCreateAppFolder, {
onSuccess() {
loadMyApps();
},
errorToast: 'Error'
});
const { runAsync: onDeleFolder } = useRequest2(delAppById, {
onSuccess() {
router.replace({
query: {
parentId: folderDetail?.parentId
}
});
},
errorToast: 'Error'
});
const RenderSearchInput = useMemo(
() => (
<InputGroup maxW={['auto', '250px']} position={'relative'}>
<MyIcon
position={'absolute'}
zIndex={10}
name={'common/searchLight'}
w={'1rem'}
color={'myGray.600'}
left={2.5}
top={'50%'}
transform={'translateY(-50%)'}
/>
<Input
value={searchKey}
onChange={(e) => setSearchKey(e.target.value)}
placeholder={appT('search_app')}
maxLength={30}
pl={8}
bg={'white'}
/>
</InputGroup>
),
[searchKey, setSearchKey, appT]
);
return (
<Flex flexDirection={'column'} h={'100%'}>
{paths.length > 0 && (
<Box pt={[4, 6]} pl={3}>
<FolderPath
paths={paths}
hoverStyle={{ bg: 'myGray.200' }}
onClick={(parentId) => {
router.push({
query: {
...router.query,
parentId
}
});
}}
/>
</Box>
)}
<Flex gap={5} flex={'1 0 0'} h={0}>
<Flex
flex={'1 0 0'}
flexDirection={'column'}
h={'100%'}
pr={folderDetail ? [3, 2] : [3, 10]}
pl={3}
overflowY={'auto'}
overflowX={'hidden'}
>
<Flex pt={paths.length > 0 ? 3 : [4, 6]} alignItems={'center'} gap={3}>
<LightRowTabs
list={[
{
label: t('app:type.All'),
value: 'ALL'
},
{
label: t('app:type.Simple bot'),
value: AppTypeEnum.simple
},
{
label: t('app:type.Workflow bot'),
value: AppTypeEnum.workflow
},
{
label: t('app:type.Plugin'),
value: AppTypeEnum.plugin
}
]}
value={appType}
inlineStyles={{ px: 0.5 }}
gap={5}
display={'flex'}
alignItems={'center'}
fontSize={['sm', 'md']}
flexShrink={0}
onChange={(e) => {
router.push({
query: {
...router.query,
type: e
}
});
}}
/>
<Box flex={1} />
{isPc && RenderSearchInput}
{(folderDetail
? folderDetail.permission.hasWritePer && folderDetail?.type !== AppTypeEnum.httpPlugin
: userInfo?.team.permission.hasWritePer) && (
<MyMenu
size="md"
Button={
<Button variant={'primary'} leftIcon={<AddIcon />}>
<Box>{t('common:common.Create New')}</Box>
</Button>
}
menuList={[
{
children: [
{
icon: 'core/app/simpleBot',
label: t('app:type.Simple bot'),
description: t('app:type.Create simple bot tip'),
onClick: () => setCreateAppType(AppTypeEnum.simple)
},
{
icon: 'core/app/type/workflowFill',
label: t('app:type.Workflow bot'),
description: t('app:type.Create workflow tip'),
onClick: () => setCreateAppType(AppTypeEnum.workflow)
},
{
icon: 'core/app/type/pluginFill',
label: t('app:type.Plugin'),
description: t('app:type.Create one plugin tip'),
onClick: () => setCreateAppType(AppTypeEnum.plugin)
},
{
icon: 'core/app/type/httpPluginFill',
label: t('app:type.Http plugin'),
description: t('app:type.Create http plugin tip'),
onClick: onOpenCreateHttpPlugin
}
]
},
{
children: [
{
icon: '/imgs/app/templateFill.svg',
label: t('app:template_market'),
description: t('app:template_market_description'),
onClick: () => setTemplateModalType('all')
}
]
},
{
children: [
{
icon: FolderIcon,
label: t('common:Folder'),
onClick: () => setEditFolder({})
}
]
}
]}
/>
)}
</Flex>
{!isPc && <Box mt={2}>{RenderSearchInput}</Box>}
<MyBox flex={'1 0 0'} isLoading={myApps.length === 0 && isFetchingApps}>
<List />
</MyBox>
</Flex>
{/* Folder slider */}
{!!folderDetail && isPc && (
<Box pt={[4, 6]} pr={[4, 6]}>
<FolderSlideCard
refetchResource={() => Promise.all([refetchFolderDetail(), loadMyApps()])}
resumeInheritPermission={() => resumeInheritPer(folderDetail._id)}
isInheritPermission={folderDetail.inheritPermission}
hasParent={!!folderDetail.parentId}
refreshDeps={[folderDetail._id, folderDetail.inheritPermission]}
name={folderDetail.name}
intro={folderDetail.intro}
onEdit={() => {
setEditFolder({
id: folderDetail._id,
name: folderDetail.name,
intro: folderDetail.intro
});
}}
onMove={() => setMoveAppId(folderDetail._id)}
deleteTip={appT('confirm_delete_folder_tip')}
onDelete={() => onDeleFolder(folderDetail._id)}
managePer={{
mode: 'all',
permission: folderDetail.permission,
onGetCollaboratorList: () => getCollaboratorList(folderDetail._id),
permissionList: AppPermissionList,
onUpdateCollaborators: ({
members,
groups,
permission
}: {
members?: string[];
groups?: string[];
permission: number;
}) => {
return postUpdateAppCollaborators({
members,
groups,
permission,
appId: folderDetail._id
});
},
refreshDeps: [folderDetail._id, folderDetail.inheritPermission],
onDelOneCollaborator: async ({
tmbId,
groupId
}: {
tmbId?: string;
groupId?: string;
}) => {
if (tmbId) {
return deleteAppCollaborators({
appId: folderDetail._id,
tmbId
});
} else if (groupId) {
return deleteAppCollaborators({
appId: folderDetail._id,
groupId
});
}
}
}}
/>
</Box>
)}
</Flex>
{!!editFolder && (
<EditFolderModal
{...editFolder}
onClose={() => setEditFolder(undefined)}
onCreate={(data) => onCreateFolder({ ...data, parentId })}
onEdit={({ id, ...data }) => onUpdateApp(id, data)}
/>
)}
{!!createAppType && (
<CreateModal
type={createAppType}
onClose={() => setCreateAppType(undefined)}
onOpenTemplateModal={setTemplateModalType}
/>
)}
{isOpenCreateHttpPlugin && <HttpEditModal onClose={onCloseCreateHttpPlugin} />}
{!!templateModalType && (
<TemplateMarketModal
onClose={() => setTemplateModalType(undefined)}
defaultType={templateModalType}
/>
)}
</Flex>
);
};
const AppListContextProvider = ({ children }: { children: ReactNode }) => {
const { t } = useTranslation();
const router = useRouter();
const { parentId = null, type = 'ALL' } = router.query as {
parentId?: string | null;
type: AppTypeEnum;
};
const [searchKey, setSearchKey] = useState('');
const {
data = [],
runAsync: loadMyApps,
loading: isFetchingApps
} = useRequest2(
() => {
const formatType = (() => {
if (!type || type === 'ALL') return undefined;
if (type === AppTypeEnum.plugin)
return [AppTypeEnum.folder, AppTypeEnum.plugin, AppTypeEnum.httpPlugin];
return [AppTypeEnum.folder, type];
})();
return getMyApps({ parentId, type: formatType, searchKey });
},
{
manual: false,
refreshDeps: [searchKey, parentId, type],
throttleWait: 500,
refreshOnWindowFocus: true
}
);
const { data: paths = [], runAsync: refetchPaths } = useRequest2(
() => getAppFolderPath(parentId),
{
manual: false,
refreshDeps: [parentId]
}
);
const { data: folderDetail, runAsync: refetchFolderDetail } = useRequest2(
() => {
if (parentId) return getAppDetailById(parentId);
return Promise.resolve(null);
},
{
manual: false,
refreshDeps: [parentId]
}
);
const { runAsync: onUpdateApp } = useRequest2((id: string, data: AppUpdateParams) =>
putAppById(id, data).then(async (res) => {
await Promise.all([refetchFolderDetail(), refetchPaths(), loadMyApps()]);
return res;
})
);
const [moveAppId, setMoveAppId] = useState<string>();
const onMoveApp = useCallback(
async (parentId: ParentIdType) => {
if (!moveAppId) return;
await onUpdateApp(moveAppId, { parentId });
},
[moveAppId, onUpdateApp]
);
const getAppFolderList = useCallback(({ parentId }: GetResourceFolderListProps) => {
return getMyApps({
parentId,
type: AppTypeEnum.folder
}).then((res) =>
res
.filter((item) => item.permission.hasWritePer)
.map((item) => ({
id: item._id,
name: item.name
}))
);
}, []);
const { setLastAppListRouteType } = useSystemStore();
useEffect(() => {
setLastAppListRouteType(type);
}, [setLastAppListRouteType, type]);
const contextValue: AppListContextType = {
parentId,
appType: type,
myApps: data,
loadMyApps,
refetchFolderDetail,
isFetchingApps,
folderDetail,
paths,
onUpdateApp,
setMoveAppId,
searchKey,
setSearchKey
};
return (
<AppListContext.Provider value={contextValue}>
{children}
{!!moveAppId && (
<MoveModal
moveResourceId={moveAppId}
server={getAppFolderList}
title={t('app:move_app')}
onClose={() => setMoveAppId(undefined)}
onConfirm={onMoveApp}
moveHint={t('app:move.hint')}
/>
)}
</AppListContext.Provider>
);
};
export default AppListContextProvider;
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。