Overview.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { makeStyles, Theme, Typography } from '@material-ui/core';
  2. import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
  3. import { useTranslation } from 'react-i18next';
  4. import EmptyCard from '../../components/cards/EmptyCard';
  5. import icons from '../../components/icons/Icons';
  6. import { WS_EVENTS, WS_EVENTS_TYPE } from '../../consts/Http';
  7. import { LOADING_STATE } from '../../consts/Milvus';
  8. import { rootContext } from '../../context/Root';
  9. import { webSokcetContext } from '../../context/WebSocket';
  10. import { useLoadAndReleaseDialogHook } from '../../hooks/Dialog';
  11. import { useNavigationHook } from '../../hooks/Navigation';
  12. import { CollectionHttp } from '../../http/Collection';
  13. import { MilvusHttp } from '../../http/Milvus';
  14. import { ALL_ROUTER_TYPES } from '../../router/Types';
  15. import { formatNumber } from '../../utils/Common';
  16. import { checkLoading, checkIndexBuilding } from '../../utils/Validation';
  17. import { CollectionData } from '../collections/Types';
  18. import CollectionCard from './collectionCard/CollectionCard';
  19. import StatisticsCard from './statisticsCard/StatisticsCard';
  20. const useStyles = makeStyles((theme: Theme) => ({
  21. collectionTitle: {
  22. margin: theme.spacing(2, 0),
  23. lineHeight: '20px',
  24. fontSize: '14px',
  25. color: '#82838e',
  26. },
  27. cardsWrapper: {
  28. display: 'grid',
  29. gridTemplateColumns: 'repeat(auto-fill, minmax(380px, 1fr))',
  30. gap: '10px',
  31. },
  32. }));
  33. const Overview = () => {
  34. useNavigationHook(ALL_ROUTER_TYPES.OVERVIEW);
  35. const { handleAction } = useLoadAndReleaseDialogHook({ type: 'collection' });
  36. const classes = useStyles();
  37. const { t: overviewTrans } = useTranslation('overview');
  38. const { t: collectionTrans } = useTranslation('collection');
  39. const { t: successTrans } = useTranslation('success');
  40. const [statistics, setStatistics] = useState<{
  41. collectionCount: number;
  42. totalData: number;
  43. }>({
  44. collectionCount: 0,
  45. totalData: 0,
  46. });
  47. const [loading, setLoading] = useState(false);
  48. const { collections, setCollections } = useContext(webSokcetContext);
  49. const { openSnackBar } = useContext(rootContext);
  50. const fetchData = useCallback(async () => {
  51. setLoading(true);
  52. const res = await CollectionHttp.getStatistics();
  53. const collections = await CollectionHttp.getCollections();
  54. const hasLoadingOrBuildingCollection = collections.some(
  55. v => checkLoading(v) || checkIndexBuilding(v)
  56. );
  57. // if some collection is building index or loading, start pulling data
  58. if (hasLoadingOrBuildingCollection) {
  59. MilvusHttp.triggerCron({
  60. name: WS_EVENTS.COLLECTION,
  61. type: WS_EVENTS_TYPE.START,
  62. });
  63. }
  64. setStatistics(res);
  65. setCollections(collections);
  66. setLoading(false);
  67. }, [setCollections]);
  68. useEffect(() => {
  69. fetchData();
  70. }, [fetchData]);
  71. const loadCollections = useMemo(
  72. () => collections.filter(c => c._status !== LOADING_STATE.UNLOADED),
  73. [collections]
  74. );
  75. const fetchRelease = async (data: CollectionData) => {
  76. const name = data._name;
  77. const res = await CollectionHttp.releaseCollection(name);
  78. openSnackBar(
  79. successTrans('release', { name: collectionTrans('collection') })
  80. );
  81. fetchData();
  82. return res;
  83. };
  84. const handleRelease = (data: CollectionData) => {
  85. handleAction(data, fetchRelease);
  86. };
  87. const statisticsData = useMemo(() => {
  88. return {
  89. data: [
  90. {
  91. label: overviewTrans('load'),
  92. value: formatNumber(loadCollections.length),
  93. valueColor: '#07d197',
  94. },
  95. {
  96. label: overviewTrans('all'),
  97. value: formatNumber(statistics.collectionCount),
  98. valueColor: '#06aff2',
  99. },
  100. {
  101. label: overviewTrans('data'),
  102. value: overviewTrans('rows', {
  103. number: formatNumber(statistics.totalData),
  104. }) as string,
  105. valueColor: '#0689d2',
  106. },
  107. ],
  108. };
  109. }, [overviewTrans, statistics, loadCollections]);
  110. const CollectionIcon = icons.navCollection;
  111. return (
  112. <section className="page-wrapper">
  113. <StatisticsCard data={statisticsData.data} />
  114. <Typography className={classes.collectionTitle}>
  115. {overviewTrans('load')}
  116. </Typography>
  117. {loadCollections.length > 0 ? (
  118. <div className={classes.cardsWrapper}>
  119. {loadCollections.map(collection => (
  120. <CollectionCard
  121. key={collection._id}
  122. data={collection}
  123. handleRelease={handleRelease}
  124. />
  125. ))}
  126. </div>
  127. ) : (
  128. <EmptyCard
  129. loading={loading}
  130. wrapperClass="page-empty-card"
  131. icon={!loading ? <CollectionIcon /> : undefined}
  132. text={
  133. loading ? overviewTrans('loading') : collectionTrans('noLoadData')
  134. }
  135. />
  136. )}
  137. </section>
  138. );
  139. };
  140. export default Overview;