index.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import { apiInterceptors, getModelList } from '@/client/api';
  2. import ModelForm from '@/components/model/model-form';
  3. import BlurredCard from '@/new-components/common/blurredCard';
  4. import ConstructLayout from '@/new-components/layout/Construct';
  5. import { IModelData } from '@/types/model';
  6. import { MODEL_ICON_DICT } from '@/utils/constants';
  7. import { PlusOutlined } from '@ant-design/icons';
  8. import { Button, Modal, Tag } from 'antd';
  9. import moment from 'moment';
  10. import { useEffect, useState } from 'react';
  11. import { useTranslation } from 'react-i18next';
  12. function Models() {
  13. const { t } = useTranslation();
  14. const [models, setModels] = useState<Array<IModelData>>([]);
  15. const [isModalOpen, setIsModalOpen] = useState(false);
  16. // const [loading, setLoading] = useState<boolean>(false);
  17. async function getModels() {
  18. const [, res] = await apiInterceptors(getModelList());
  19. setModels(res ?? []);
  20. }
  21. // TODO: delete unuesed function
  22. // async function stopTheModel(info: IModelData) {
  23. // if (loading) {
  24. // return;
  25. // }
  26. // setLoading(true);
  27. // const [, res] = await apiInterceptors(
  28. // stopModel({
  29. // host: info.host,
  30. // port: info.port,
  31. // model: info.model_name,
  32. // worker_type: info.model_type,
  33. // params: {},
  34. // }),
  35. // );
  36. // setLoading(false);
  37. // if (res === true) {
  38. // message.success(t('stop_model_success'));
  39. // }
  40. // }
  41. useEffect(() => {
  42. getModels();
  43. }, []);
  44. // TODO: unuesed function
  45. // const onSearch = useDebounceFn(
  46. // async (e: any) => {
  47. // const v = e.target.value;
  48. // await modelSearch({ model_name: v });
  49. // },
  50. // { wait: 500 },
  51. // ).run;
  52. const returnLogo = (name: string) => {
  53. const formatterModal = name?.replaceAll('-', '_').split('_')[0];
  54. const dict = Object.keys(MODEL_ICON_DICT);
  55. for (let i = 0; i < dict.length; i++) {
  56. const element = dict[i];
  57. if (formatterModal?.includes(element)) {
  58. return MODEL_ICON_DICT[element];
  59. }
  60. }
  61. return '/pictures/model.png';
  62. };
  63. return (
  64. <ConstructLayout>
  65. <div className='px-6 overflow-y-auto'>
  66. <div className='flex justify-between items-center mb-6'>
  67. <div className='flex items-center gap-4'>
  68. {/* <Input
  69. variant="filled"
  70. prefix={<SearchOutlined />}
  71. placeholder={t('please_enter_the_keywords')}
  72. onChange={onSearch}
  73. onPressEnter={onSearch}
  74. allowClear
  75. className="w-[230px] h-[40px] border-1 border-white backdrop-filter backdrop-blur-lg bg-white bg-opacity-30 dark:border-[#6f7f95] dark:bg-[#6f7f95] dark:bg-opacity-60"
  76. /> */}
  77. </div>
  78. <div className='flex items-center gap-4'>
  79. <Button
  80. className='border-none text-white bg-button-gradient'
  81. icon={<PlusOutlined />}
  82. onClick={() => {
  83. setIsModalOpen(true);
  84. }}
  85. >
  86. {t('create_model')}
  87. </Button>
  88. </div>
  89. </div>
  90. <div className='flex flex-wrap mx-[-8px] '>
  91. {models.map(item => (
  92. <BlurredCard
  93. logo={returnLogo(item.model_name)}
  94. description={
  95. <div className='flex flex-col gap-1 relative text-xs bottom-4'>
  96. <div className='flex overflow-hidden'>
  97. <p className='w-28 text-gray-500 mr-2'>Host:</p>
  98. <p className='flex-1 text-ellipsis'>{item.host}</p>
  99. </div>
  100. <div className='flex overflow-hidden'>
  101. <p className='w-28 text-gray-500 mr-2'>Manage Host:</p>
  102. <p className='flex-1 text-ellipsis'>
  103. {item.manager_host}:{item.manager_port}
  104. </p>
  105. </div>
  106. <div className='flex overflow-hidden'>
  107. <p className='w-28 text-gray-500 mr-2'>Last Heart Beat:</p>
  108. <p className='flex-1 text-ellipsis'>{moment(item.last_heartbeat).format('YYYY-MM-DD')}</p>
  109. </div>
  110. </div>
  111. }
  112. name={item.model_name}
  113. key={item.model_name}
  114. rightTopHover={false}
  115. Tags={
  116. <div>
  117. <Tag color={item.healthy ? 'green' : 'red'}>{item.healthy ? 'Healthy' : 'Unhealthy'}</Tag>
  118. <Tag>{item.model_type}</Tag>
  119. </div>
  120. }
  121. />
  122. ))}
  123. </div>
  124. <Modal
  125. width={800}
  126. open={isModalOpen}
  127. title={t('create_model')}
  128. onCancel={() => {
  129. setIsModalOpen(false);
  130. }}
  131. footer={null}
  132. >
  133. <ModelForm
  134. onCancel={() => {
  135. setIsModalOpen(false);
  136. }}
  137. onSuccess={() => {
  138. setIsModalOpen(false);
  139. getModels();
  140. }}
  141. />
  142. </Modal>
  143. </div>
  144. </ConstructLayout>
  145. );
  146. }
  147. export default Models;