Overview.tsx 4.4 KB

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