From 2095cc4dec96a66a50821d56444eeb77717b1972 Mon Sep 17 00:00:00 2001 From: Abhishek Pal Date: Tue, 26 Aug 2025 16:02:34 +0530 Subject: [PATCH 1/7] HDDS-13542. Add individual API calls for cards --- .../recon/ozone-recon-web/src/app.less | 17 + .../autoReloadPanel/autoReloadPanelHooks.tsx | 120 ++++++ .../src/utils/autoReloadHelper.tsx | 4 + .../errorBoundary.tsx | 0 .../src/v2/components/errors/errorMessage.tsx | 32 ++ .../overviewCard/overviewSimpleCard.tsx | 9 +- .../overviewCard/overviewStorageCard.tsx | 20 +- .../overviewCard/overviewSummaryCard.tsx | 21 +- .../insights/containerMismatchTable.tsx | 2 +- .../insights/deletePendingDirsTable.tsx | 2 +- .../insights/deletePendingKeysTable.tsx | 2 +- .../insights/deletedContainerKeysTable.tsx | 2 +- .../tables/insights/openKeysTable.tsx | 2 +- .../src/v2/hooks/useAPIData.hook.ts | 156 ++++++++ .../src/v2/hooks/useAutoReload.hook.tsx | 78 ++++ .../src/v2/hooks/useAutoReloadPanel.hook.tsx | 55 +++ .../src/v2/hooks/useAutoReloadState.hook.tsx | 42 ++ .../{debounce.hook.tsx => useDebounce.tsx} | 0 .../src/v2/pages/buckets/buckets.tsx | 2 +- .../src/v2/pages/containers/containers.tsx | 2 +- .../src/v2/pages/datanodes/datanodes.tsx | 2 +- .../pages/overview/components/SummaryCard.tsx | 78 ++++ .../src/v2/pages/overview/overview.tsx | 369 ++++++------------ .../src/v2/pages/pipelines/pipelines.tsx | 2 +- .../src/v2/pages/volumes/volumes.tsx | 2 +- .../src/v2/types/overview.types.ts | 37 +- 26 files changed, 777 insertions(+), 281 deletions(-) create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/components/autoReloadPanel/autoReloadPanelHooks.tsx rename hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/{errorBoundary => errors}/errorBoundary.tsx (100%) create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/errors/errorMessage.tsx create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/hooks/useAPIData.hook.ts create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/hooks/useAutoReload.hook.tsx create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/hooks/useAutoReloadPanel.hook.tsx create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/hooks/useAutoReloadState.hook.tsx rename hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/hooks/{debounce.hook.tsx => useDebounce.tsx} (100%) create mode 100644 hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/overview/components/SummaryCard.tsx diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.less b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.less index 44f53fa9d47d..073949e476a4 100644 --- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.less +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.less @@ -169,4 +169,21 @@ body { .data-container { padding: 24px; height: 80vh; +} + +.error-msg { + display: flex; + align-items: center; + flex-direction: column; + color: #6d6d6d; + margin: 40px auto; + + #error-icon { + font-size: 42px; + padding-bottom: 12px; + } + + #error-txt { + font-size: 18px; + } } \ No newline at end of file diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/components/autoReloadPanel/autoReloadPanelHooks.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/components/autoReloadPanel/autoReloadPanelHooks.tsx new file mode 100644 index 000000000000..86b9121799f1 --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/components/autoReloadPanel/autoReloadPanelHooks.tsx @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import moment from 'moment'; +import { Tooltip, Button, Switch } from 'antd'; +import { PlayCircleOutlined, ReloadOutlined } from '@ant-design/icons'; +import { useLocation } from 'react-router-dom'; + +import { useAutoReloadState } from '@/v2/hooks/useAutoReloadState.hook'; +import './autoReloadPanel.less'; + +interface IAutoReloadPanelProps { + onReload: () => void; + lastRefreshed: number; + lastUpdatedOMDBDelta: number; + lastUpdatedOMDBFull: number; + isLoading: boolean; + omStatus: string; + togglePolling: (isEnabled: boolean) => void; + omSyncLoad: () => void; +} + +const AutoReloadPanel: React.FC = ({ + onReload, + lastRefreshed, + lastUpdatedOMDBDelta, + lastUpdatedOMDBFull, + isLoading, + omSyncLoad, + omStatus, + togglePolling +}) => { + const { autoReloadEnabled, updateAutoReloadState } = useAutoReloadState(); + const location = useLocation(); + + const autoReloadToggleHandler = (checked: boolean) => { + updateAutoReloadState(checked); + togglePolling(checked); + }; + + const lastRefreshedText = lastRefreshed === 0 || lastRefreshed === undefined ? 'NA' : + ( + + {moment(lastRefreshed).format('LT')} + + ); + + const omSyncStatusDisplay = omStatus === '' ? '' : omStatus ?
OM DB update is successfully triggered.
:
OM DB update is already running.
; + + const omDBDeltaFullToolTip = + {omSyncStatusDisplay} + {'Delta Update'}: {moment(lastUpdatedOMDBDelta).fromNow()}, {moment(lastUpdatedOMDBDelta).format('LT')} +
+ {'Full Update'}: {moment(lastUpdatedOMDBFull).fromNow()}, {moment(lastUpdatedOMDBFull).format('LT')} +
+ + const lastUpdatedOMLatest = lastUpdatedOMDBDelta > lastUpdatedOMDBFull ? lastUpdatedOMDBDelta : lastUpdatedOMDBFull; + + const lastUpdatedDeltaFullToolTip = lastUpdatedOMDBDelta === 0 || lastUpdatedOMDBDelta === undefined || lastUpdatedOMDBFull === 0 || lastUpdatedOMDBFull === undefined ? 'NA' : + ( + + {moment(lastUpdatedOMLatest).format('LT')} + + ); + + const lastUpdatedDeltaFullText = lastUpdatedOMDBDelta === 0 || lastUpdatedOMDBDelta === undefined || lastUpdatedOMDBFull === 0 || lastUpdatedOMDBFull === undefined ? '' : + //omSyncLoad should be clickable at all times. If the response from the dbsync is false it will show DB update is already running else show triggered sync + ( + <> +   | DB Synced at {lastUpdatedDeltaFullToolTip} +