market-plugins.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import {
  2. apiInterceptors,
  3. postAgentHubUpdate,
  4. postAgentInstall,
  5. postAgentQuery,
  6. postAgentUninstall,
  7. } from '@/client/api';
  8. import BlurredCard, { ChatButton } from '@/new-components/common/blurredCard';
  9. import { PostAgentQueryParams } from '@/types/agent';
  10. import { ClearOutlined, DownloadOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons';
  11. import { useRequest } from 'ahooks';
  12. import { Button, Form, Input, Spin, Tag, message } from 'antd';
  13. import moment from 'moment';
  14. import { useCallback, useMemo, useState } from 'react';
  15. import { useTranslation } from 'react-i18next';
  16. import MyEmpty from '../common/MyEmpty';
  17. function MarketPlugins() {
  18. const { t } = useTranslation();
  19. const [uploading, setUploading] = useState(false);
  20. const [isError, setIsError] = useState(false);
  21. const [actionIndex, setActionIndex] = useState<number | undefined>();
  22. const [form] = Form.useForm<PostAgentQueryParams['filter']>();
  23. const pagination = useMemo<{ pageNo: number; pageSize: number }>(
  24. () => ({
  25. pageNo: 1,
  26. pageSize: 20,
  27. }),
  28. [],
  29. );
  30. const {
  31. data: agents = [],
  32. loading,
  33. refresh,
  34. } = useRequest(async () => {
  35. const queryParams: PostAgentQueryParams = {
  36. page_index: pagination.pageNo,
  37. page_size: pagination.pageSize,
  38. filter: form.getFieldsValue(),
  39. };
  40. const [err, res] = await apiInterceptors(postAgentQuery(queryParams));
  41. setIsError(!!err);
  42. return res?.datas ?? [];
  43. });
  44. const updateFromGithub = async () => {
  45. try {
  46. setUploading(true);
  47. const [err] = await apiInterceptors(postAgentHubUpdate());
  48. if (err) return;
  49. message.success('success');
  50. refresh();
  51. } finally {
  52. setUploading(false);
  53. }
  54. };
  55. const pluginAction = useCallback(
  56. async (name: string, index: number, isInstall: boolean) => {
  57. if (actionIndex) return;
  58. setActionIndex(index);
  59. const [err] = await apiInterceptors((isInstall ? postAgentInstall : postAgentUninstall)(name));
  60. if (!err) {
  61. message.success('success');
  62. refresh();
  63. }
  64. setActionIndex(undefined);
  65. },
  66. [actionIndex, refresh],
  67. );
  68. // const renderAction = useCallback(
  69. // (agent: IAgentPlugin, index: number) => {
  70. // if (index === actionIndex) {
  71. // return <LoadingOutlined />;
  72. // }
  73. // return agent.installed ? (
  74. // <Tooltip title='Uninstall'>
  75. // <div
  76. // className='w-full h-full'
  77. // onClick={() => {
  78. // pluginAction(agent.name, index, false);
  79. // }}
  80. // >
  81. // <ClearOutlined />
  82. // </div>
  83. // </Tooltip>
  84. // ) : (
  85. // <Tooltip title='Install'>
  86. // <div
  87. // className='w-full h-full'
  88. // onClick={() => {
  89. // pluginAction(agent.name, index, true);
  90. // }}
  91. // >
  92. // <DownloadOutlined />
  93. // </div>
  94. // </Tooltip>
  95. // );
  96. // },
  97. // [actionIndex, pluginAction],
  98. // );
  99. console.log(agents);
  100. return (
  101. <Spin spinning={loading}>
  102. <Form form={form} layout='inline' onFinish={refresh} className='mb-2'>
  103. <Form.Item className='!mb-2' name='name' label={'Name'}>
  104. <Input allowClear className='w-48' />
  105. </Form.Item>
  106. <Form.Item>
  107. <Button className='mr-2' type='primary' htmlType='submit' icon={<SearchOutlined />}>
  108. {t('Search')}
  109. </Button>
  110. <Button loading={uploading} type='primary' icon={<SyncOutlined />} onClick={updateFromGithub}>
  111. {t('Update_From_Github')}
  112. </Button>
  113. </Form.Item>
  114. </Form>
  115. {!agents.length && !loading && <MyEmpty error={isError} refresh={refresh} />}
  116. <div className='flex flex-wrap gap-2 md:gap-4'>
  117. {/* <Card
  118. className="w-full md:w-1/2 lg:w-1/3 xl:w-1/4"
  119. key={agent.id}
  120. actions={[
  121. renderAction(agent, index),
  122. <Tooltip key="github" title="Github">
  123. <div
  124. className="w-full h-full"
  125. onClick={() => {
  126. window.open(agent.storage_url, '_blank');
  127. }}
  128. >
  129. <GithubOutlined />
  130. </div>
  131. </Tooltip>,
  132. ]}
  133. >
  134. <Tooltip title={agent.name}>
  135. <h2 className="mb-2 text-base font-semibold line-clamp-1">{agent.name}</h2>
  136. </Tooltip>
  137. {agent.author && <Tag>{agent.author}</Tag>}
  138. {agent.version && <Tag>v{agent.version}</Tag>}
  139. {agent.type && <Tag>Type {agent.type}</Tag>}
  140. {agent.storage_channel && <Tag>{agent.storage_channel}</Tag>}
  141. <Tooltip title={agent.description}>
  142. <p className="mt-2 line-clamp-2 text-gray-400 text-sm">{agent.description}</p>
  143. </Tooltip>
  144. </Card> */}
  145. {agents.map((agent, index) => (
  146. <BlurredCard
  147. onClick={() => {
  148. window.open(agent.storage_url, '_blank');
  149. }}
  150. description={agent.description}
  151. name={agent.name}
  152. key={agent.id}
  153. Tags={
  154. <div>
  155. {agent.author && <Tag>{agent.author}</Tag>}
  156. {agent.version && <Tag>v{agent.version}</Tag>}
  157. {agent.type && <Tag>Type {agent.type}</Tag>}
  158. {agent.storage_channel && <Tag>{agent.storage_channel}</Tag>}
  159. </div>
  160. }
  161. LeftBottom={
  162. <div className='flex gap-2'>
  163. <span>{agent.author}</span>
  164. <span>•</span>
  165. {agent?.gmt_created && <span>{moment(agent?.gmt_created).fromNow() + ' ' + t('update')}</span>}
  166. </div>
  167. }
  168. RightBottom={
  169. agent.installed ? (
  170. <ChatButton
  171. Icon={<ClearOutlined />}
  172. text='Uninstall'
  173. onClick={() => {
  174. pluginAction(agent.name, index, false);
  175. }}
  176. />
  177. ) : (
  178. <ChatButton
  179. Icon={<DownloadOutlined />}
  180. text='Install'
  181. onClick={() => {
  182. pluginAction(agent.name, index, true);
  183. }}
  184. />
  185. )
  186. }
  187. />
  188. ))}
  189. </div>
  190. </Spin>
  191. );
  192. }
  193. export default MarketPlugins;