|
1 | 1 | import {ReactNode, useCallback} from 'react'; |
2 | | -import {shallowEqual, useDispatch, useSelector} from 'react-redux'; |
| 2 | +import {shallowEqual, useDispatch} from 'react-redux'; |
3 | 3 |
|
4 | 4 | import {Loader} from '../../../../components/Loader'; |
5 | | - |
6 | | -//@ts-ignore |
7 | 5 | import {TableIndexInfo} from '../../../../components/InfoViewer/schemaInfo'; |
8 | 6 | import {ResponseError} from '../../../../components/Errors/ResponseError'; |
9 | 7 |
|
10 | | -import {TopicInfo} from './TopicInfo'; |
11 | | -import {ChangefeedInfo} from './ChangefeedInfo'; |
12 | | -import {TableInfo} from './TableInfo'; |
13 | | - |
14 | 8 | import {EPathType} from '../../../../types/api/schema'; |
| 9 | +import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks'; |
| 10 | +import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema/schema'; |
| 11 | +import {getTopic} from '../../../../store/reducers/topic'; |
| 12 | +import { |
| 13 | + getOlapStats, |
| 14 | + resetLoadingState as resetOlapLoadingState, |
| 15 | +} from '../../../../store/reducers/olapStats'; |
| 16 | +import { |
| 17 | + getOverview, |
| 18 | + getOverviewBatched, |
| 19 | + setCurrentOverviewPath, |
| 20 | + setDataWasNotLoaded, |
| 21 | +} from '../../../../store/reducers/overview/overview'; |
| 22 | + |
15 | 23 | import { |
16 | 24 | isEntityWithMergedImplementation, |
17 | 25 | isColumnEntityType, |
18 | 26 | isTableType, |
19 | 27 | isPathTypeWithTopic, |
20 | 28 | } from '../../utils/schema'; |
21 | | -//@ts-ignore |
22 | | -import { |
23 | | - getSchema, |
24 | | - getSchemaBatched, |
25 | | - resetLoadingState, |
26 | | - selectSchemaMergedChildrenPaths, |
27 | | -} from '../../../../store/reducers/schema/schema'; |
28 | | -import {getTopic} from '../../../../store/reducers/topic'; |
29 | | -//@ts-ignore |
30 | | -import { |
31 | | - getOlapStats, |
32 | | - resetLoadingState as resetOlapLoadingState, |
33 | | -} from '../../../../store/reducers/olapStats'; |
34 | | -import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks'; |
| 29 | + |
| 30 | +import {TopicInfo} from './TopicInfo'; |
| 31 | +import {ChangefeedInfo} from './ChangefeedInfo'; |
| 32 | +import {TableInfo} from './TableInfo'; |
35 | 33 |
|
36 | 34 | interface OverviewProps { |
37 | 35 | type?: EPathType; |
38 | | - className?: string; |
39 | 36 | tenantName?: string; |
40 | 37 | } |
41 | 38 |
|
42 | | -function Overview({type, tenantName, className}: OverviewProps) { |
| 39 | +function Overview({type, tenantName}: OverviewProps) { |
43 | 40 | const dispatch = useDispatch(); |
44 | 41 |
|
| 42 | + const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema); |
45 | 43 | const { |
46 | | - currentSchema: currentItem = {}, |
47 | | - loading: schemaLoading, |
48 | | - wasLoaded, |
49 | | - autorefresh, |
50 | | - currentSchemaPath, |
51 | | - error, |
52 | | - } = useSelector((state: any) => state.schema); |
53 | | - |
54 | | - const {data: {result: olapStats} = {result: undefined}, loading: olapStatsLoading} = |
55 | | - useTypedSelector((state) => state.olapStats); |
56 | | - |
57 | | - const loading = schemaLoading || olapStatsLoading; |
| 44 | + data, |
| 45 | + additionalData, |
| 46 | + loading: overviewLoading, |
| 47 | + wasLoaded: overviewWasLoaded, |
| 48 | + error: overviewError, |
| 49 | + } = useTypedSelector((state) => state.overview); |
| 50 | + const { |
| 51 | + data: {result: olapStats} = {result: undefined}, |
| 52 | + loading: olapStatsLoading, |
| 53 | + wasLoaded: olapStatsWasLoaded, |
| 54 | + } = useTypedSelector((state) => state.olapStats); |
58 | 55 |
|
59 | 56 | const isEntityWithMergedImpl = isEntityWithMergedImplementation(type); |
60 | 57 |
|
61 | | - // There is a circular dependency here. Fetch data depends on children paths |
62 | | - // When data in store updated on fetch request, |
63 | | - // new object is set there, so source children array is updated |
64 | | - // This updates selector, the selector returns a new array, and data is fetched again |
65 | | - // To prevent it, shallowEqual, which compares array content, was added |
| 58 | + // shalloEqual prevents rerenders when new schema data is loaded |
66 | 59 | const mergedChildrenPaths = useTypedSelector( |
67 | 60 | (state) => selectSchemaMergedChildrenPaths(state, currentSchemaPath, type), |
68 | 61 | shallowEqual, |
69 | 62 | ); |
70 | 63 |
|
| 64 | + const entityLoading = |
| 65 | + (overviewLoading && !overviewWasLoaded) || (olapStatsLoading && !olapStatsWasLoaded); |
| 66 | + const entityNotReady = isEntityWithMergedImpl && !mergedChildrenPaths; |
| 67 | + |
71 | 68 | const fetchData = useCallback( |
72 | 69 | (isBackground: boolean) => { |
73 | | - if (!isBackground) { |
74 | | - dispatch(resetLoadingState()); |
| 70 | + const schemaPath = currentSchemaPath || tenantName; |
| 71 | + |
| 72 | + if (!schemaPath) { |
| 73 | + return; |
75 | 74 | } |
76 | 75 |
|
77 | | - const schemaPath = currentSchemaPath || tenantName; |
| 76 | + dispatch(setCurrentOverviewPath(schemaPath)); |
| 77 | + |
| 78 | + if (!isBackground) { |
| 79 | + dispatch(setDataWasNotLoaded()); |
| 80 | + } |
78 | 81 |
|
79 | 82 | if (!isEntityWithMergedImpl) { |
80 | | - dispatch(getSchema({path: schemaPath})); |
| 83 | + dispatch(getOverview({path: schemaPath})); |
81 | 84 | } else if (mergedChildrenPaths) { |
82 | | - dispatch(getSchemaBatched([schemaPath, ...mergedChildrenPaths])); |
| 85 | + dispatch(getOverviewBatched([schemaPath, ...mergedChildrenPaths])); |
83 | 86 | } |
84 | 87 |
|
85 | 88 | if (isTableType(type) && isColumnEntityType(type)) { |
@@ -113,32 +116,32 @@ function Overview({type, tenantName, className}: OverviewProps) { |
113 | 116 | [EPathType.EPathTypeDir]: undefined, |
114 | 117 | [EPathType.EPathTypeTable]: undefined, |
115 | 118 | [EPathType.EPathTypeSubDomain]: undefined, |
116 | | - [EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={currentItem} />, |
| 119 | + [EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={data} />, |
117 | 120 | [EPathType.EPathTypeExtSubDomain]: undefined, |
118 | 121 | [EPathType.EPathTypeColumnStore]: undefined, |
119 | 122 | [EPathType.EPathTypeColumnTable]: undefined, |
120 | 123 | [EPathType.EPathTypeCdcStream]: () => ( |
121 | | - <ChangefeedInfo data={currentItem} childrenPaths={mergedChildrenPaths} /> |
| 124 | + <ChangefeedInfo data={data} topic={additionalData?.[0]} /> |
122 | 125 | ), |
123 | | - [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={currentItem} />, |
| 126 | + [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={data} />, |
124 | 127 | }; |
125 | 128 |
|
126 | 129 | return ( |
127 | 130 | (type && pathTypeToComponent[type]?.()) || ( |
128 | | - <TableInfo data={currentItem} type={type} olapStats={olapStats} /> |
| 131 | + <TableInfo data={data} type={type} olapStats={olapStats} /> |
129 | 132 | ) |
130 | 133 | ); |
131 | 134 | }; |
132 | 135 |
|
133 | | - if ((loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths)) { |
| 136 | + if (entityLoading || entityNotReady) { |
134 | 137 | return <Loader size="m" />; |
135 | 138 | } |
136 | 139 |
|
137 | | - if (error) { |
138 | | - return <ResponseError error={error} />; |
| 140 | + if (overviewError) { |
| 141 | + return <ResponseError error={overviewError} />; |
139 | 142 | } |
140 | 143 |
|
141 | | - return <div className={className}>{renderContent()}</div>; |
| 144 | + return <div>{renderContent()}</div>; |
142 | 145 | } |
143 | 146 |
|
144 | 147 | export default Overview; |
0 commit comments