Overview.tsx 4.5 KB

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