This is an automated email from the ASF dual-hosted git repository.
jerryshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new f350927f96 [#12289] web-v2(UI): fix about retains the previous
sub-path when switching filesets (#12292)
f350927f96 is described below
commit f350927f9626cfd1eed3102da5ef31d5f0c406fb
Author: Qian Xia <[email protected]>
AuthorDate: Mon Aug 3 17:27:02 2026 +0800
[#12289] web-v2(UI): fix about retains the previous sub-path when switching
filesets (#12292)
### What changes were proposed in this pull request?
1. page.js — Add resetActivatedDetails() for the fileset branch
(consistent with the table branch), clearing stale activatedDetails
before loading new data.
2. FilesetDetailsPage.js — Guard ListFiles rendering with
!store.activatedDetailsLoading to prevent mounting before new details
are ready.
3. ListFiles.js — Three fixes:
- Render-time reset: Detect filesetIdentity change via useRef and reset
sub_path/currentLocation immediately during render (before useEffects
run).
- Stale props detection: Track which fileset the storageLocations prop
belongs to. Block API calls and show loading spinner when
storageLocations is stale.
- currentLocation sync: Derive currentLocation from
storageLocations/defaultLocationName when it's undefined or invalid,
instead of blindly trusting the previous value.
### Why are the changes needed?
Fix: #12289
### Does this PR introduce _any_ user-facing change?
N/A
### How was this patch tested?
munaully
---
web-v2/web/src/app/catalogs/page.js | 1 +
.../entitiesContent/FilesetDetailsPage.js | 3 +-
.../rightContent/entitiesContent/ListFiles.js | 42 +++++++++++++---------
3 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/web-v2/web/src/app/catalogs/page.js
b/web-v2/web/src/app/catalogs/page.js
index 9e8b2e5b3a..9aeecc3705 100644
--- a/web-v2/web/src/app/catalogs/page.js
+++ b/web-v2/web/src/app/catalogs/page.js
@@ -253,6 +253,7 @@ const CatalogsListPage = () => {
case 'fileset':
store.filesets.length === 0 &&
(await dispatch(fetchFilesets({ init: true, page: 'schemas',
metalake, catalog, schema })))
+ await dispatch(resetActivatedDetails())
await dispatch(setActivatedDetailsLoading(true))
await dispatch(getFilesetDetails({ init: true, metalake,
catalog, schema, fileset }))
await dispatch(setActivatedDetailsLoading(false))
diff --git
a/web-v2/web/src/app/catalogs/rightContent/entitiesContent/FilesetDetailsPage.js
b/web-v2/web/src/app/catalogs/rightContent/entitiesContent/FilesetDetailsPage.js
index ad34e2136c..f6289ac64d 100644
---
a/web-v2/web/src/app/catalogs/rightContent/entitiesContent/FilesetDetailsPage.js
+++
b/web-v2/web/src/app/catalogs/rightContent/entitiesContent/FilesetDetailsPage.js
@@ -265,9 +265,10 @@ export default function FilesetDetailsPage({ ...props }) {
</Space>
</Spin>
<Tabs items={tabOptions} activeKey={activeTab} onChange={setActiveTab} />
- {activeTab === 'files' && (
+ {activeTab === 'files' && !store.activatedDetailsLoading && (
<div data-refer='tab-files-panel'>
<ListFiles
+ key={`${catalog}.${schema}.${fileset}`}
metalake={currentMetalake}
catalog={catalog}
schema={schema}
diff --git
a/web-v2/web/src/app/catalogs/rightContent/entitiesContent/ListFiles.js
b/web-v2/web/src/app/catalogs/rightContent/entitiesContent/ListFiles.js
index 3fd84ba3f9..ed6cc4d84d 100644
--- a/web-v2/web/src/app/catalogs/rightContent/entitiesContent/ListFiles.js
+++ b/web-v2/web/src/app/catalogs/rightContent/entitiesContent/ListFiles.js
@@ -41,11 +41,28 @@ const ListFiles = ({ metalake, catalog, schema, fileset,
storageLocations, defau
const store = useAppSelector(state => state.metalakes)
const dispatch = useAppDispatch()
+ // Sync currentLocation with storageLocations/defaultLocationName.
+ // When currentLocation is undefined or no longer exists in
+ // storageLocations, derive the correct value from props.
useEffect(() => {
- if (defaultLocationName) {
+ if (!storageLocations || Object.keys(storageLocations).length === 0) {
+ setCurrentLocation(undefined)
+
+ return
+ }
+
+ // If currentLocation is valid in current storageLocations, keep it
+ if (currentLocation && storageLocations[currentLocation]) {
+ return
+ }
+
+ // Otherwise, derive from props
+ if (defaultLocationName && storageLocations[defaultLocationName]) {
setCurrentLocation(defaultLocationName)
+ } else {
+ setCurrentLocation(Object.keys(storageLocations)[0])
}
- }, [defaultLocationName])
+ }, [currentLocation, defaultLocationName, storageLocations])
useEffect(() => {
if (sub_path) {
@@ -56,7 +73,7 @@ const ListFiles = ({ metalake, catalog, schema, fileset,
storageLocations, defau
}, [sub_path])
useEffect(() => {
- if (metalake && catalog && schema && fileset) {
+ if (metalake && catalog && schema && fileset && currentLocation &&
storageLocations?.[currentLocation]) {
dispatch(
getFilesetFiles({
metalake,
@@ -149,25 +166,16 @@ const ListFiles = ({ metalake, catalog, schema, fileset,
storageLocations, defau
return { columns, minWidth: 100 }
}, [columns])
- if (!storageLocations || Object.keys(storageLocations).length === 0) {
- return <p>No storage locations configured</p>
- }
-
- if (!currentLocation && defaultLocationName) {
- setCurrentLocation(defaultLocationName)
-
+ if (!storageLocations) {
return <Spin />
}
- if (!currentLocation && Object.keys(storageLocations).length > 0) {
- const firstLocation = Object.keys(storageLocations)[0]
- setCurrentLocation(firstLocation)
-
- return <Spin />
+ if (Object.keys(storageLocations).length === 0) {
+ return <Text type='secondary'>No storage locations configured</Text>
}
- if (!currentLocation) {
- return <p>Please select a storage location</p>
+ if (!currentLocation || !storageLocations[currentLocation]) {
+ return <Spin />
}
const displayedFiles = [...store.tableData] || []