diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/GlobalPageSize.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/GlobalPageSize.spec.ts
index 7f568ad03737..6c44205bbae4 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/GlobalPageSize.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/GlobalPageSize.spec.ts
@@ -28,8 +28,18 @@ test.describe('Table & Data Model columns table pagination', () => {
await waitForAllLoadersToDisappear(page);
// Change page size to 25
- await page.getByTestId('page-size-selection-dropdown').click();
- await page.getByRole('menuitem', { name: '25 / Page' }).click();
+ const tablePageSizeDropdown = page.getByTestId(
+ 'page-size-selection-dropdown'
+ );
+ await tablePageSizeDropdown.scrollIntoViewIfNeeded();
+ await expect(tablePageSizeDropdown).toBeVisible();
+ await tablePageSizeDropdown.hover();
+
+ const tablePageSizeOption = page
+ .locator('.ant-dropdown:not(.ant-dropdown-hidden)')
+ .getByRole('menuitem', { name: '25 / Page' });
+ await expect(tablePageSizeOption).toBeVisible();
+ await tablePageSizeOption.click();
await waitForAllLoadersToDisappear(page);
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts
index a1cf6d76b7fb..5e92f5492f8d 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts
@@ -342,59 +342,34 @@ test.describe.serial('Domain and Data Product Asset Counts', () => {
await waitForAllLoadersToDisappear(page);
await sidebarClick(page, SidebarItem.DATA_PRODUCT);
await selectDataProduct(page, dataProduct.data);
+ await waitForAllLoadersToDisappear(page);
+ const dataProductAssetsResponse = page.waitForResponse(
+ (response) =>
+ response.url().includes('/api/v1/dataProducts/name/') &&
+ response.url().includes('fields=domains%2Cassets') &&
+ response.request().method() === 'GET'
+ );
await page.getByTestId('assets').click();
+ await dataProductAssetsResponse;
- await page
- .getByTestId('loader')
- .waitFor({
- state: 'detached',
- timeout: 10000,
- })
- .catch(() => {
- /* ignore if loader not found */
- });
-
- let hasAssets = true;
- while (hasAssets) {
- const checkboxes = page.locator(
- '[data-testid^="table-data-card_"] input[type="checkbox"]'
- );
- const count = await checkboxes.count();
-
- if (count === 0) {
- hasAssets = false;
- break;
- }
-
- const selectAll = page.getByRole('checkbox', { name: 'Select All' });
- if (await selectAll.isVisible()) {
- await selectAll.check();
- } else {
- for (let i = 0; i < count; i++) {
- await checkboxes.nth(i).check();
- }
- }
-
- const previousCount = count;
- const removeRes = page.waitForResponse('**/assets/remove');
- await page.getByTestId('delete-all-button').click();
- await removeRes;
-
- await expect
- .poll(
- async () =>
- page
- .locator(
- '[data-testid^="table-data-card_"] input[type="checkbox"]'
- )
- .count(),
- { timeout: 10_000 }
- )
- .toBeLessThan(previousCount);
+ // The card list paints after the assets response resolves, and count()
+ // does not auto-wait. Wait for a card before selecting every attached asset.
+ await waitForAllLoadersToDisappear(page);
+ const assetCard = page.locator('[data-testid^="table-data-card_"]');
+ await assetCard.first().waitFor({ state: 'visible' });
+
+ const attachedCount = await assetCard.count();
+ for (let i = 0; i < attachedCount; i++) {
+ await assetCard.nth(i).locator('input[type="checkbox"]').check();
}
+ const removeRes = page.waitForResponse('**/assets/remove');
+ await page.getByTestId('delete-all-button').click();
+ await removeRes;
+
await page.reload();
+ await waitForAllLoadersToDisappear(page);
await checkAssetsCount(page, 0);
await redirectToHomePage(page);
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts
index 6cb8c799a4c3..80f1f76cce21 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts
@@ -1258,11 +1258,11 @@ test.describe('Glossary tests', () => {
await selectActiveGlossary(page, glossary1.data.displayName);
await selectActiveGlossaryTerm(page, glossaryTerm1.data.displayName);
- const viewerContainerText = await page.textContent(
- '[data-testid="viewer-container"]'
- );
-
- expect(viewerContainerText).toContain('Updated description');
+ // The description renders after the term page finishes loading, so assert
+ // on the locator rather than reading textContent once.
+ await expect(
+ page.locator('[data-testid="viewer-container"]')
+ ).toContainText('Updated description');
} finally {
await glossaryTerm1.delete(apiContext);
await glossary1.delete(apiContext);
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/odcsImportExport.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/odcsImportExport.ts
index c30ab52bd12c..973eeccb0cea 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/utils/odcsImportExport.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/odcsImportExport.ts
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Page, Response } from '@playwright/test';
+import { expect, Page, Response } from '@playwright/test';
import { TableClass } from '../support/entity/TableClass';
import { toastNotification } from './common';
import { waitForAllLoadersToDisappear } from './entity';
@@ -25,17 +25,22 @@ export const openODCSImportDropdown = async (page: Page) => {
const addButton = page.getByTestId('add-contract-button');
const manageButton = page.getByTestId('manage-contract-actions');
- const addButtonVisible = await addButton.isVisible().catch(() => false);
- const manageButtonVisible = await manageButton.isVisible().catch(() => false);
+ // Contract actions can render after the page loader disappears, so wait for
+ // either valid entry point instead of making a one-shot visibility decision.
+ await expect(addButton.or(manageButton)).toBeVisible({ timeout: 15000 });
- if (addButtonVisible) {
+ if (await addButton.isVisible()) {
await addButton.click();
await page.getByTestId('add-contract-menu').waitFor({
state: 'visible',
timeout: 10000,
});
- } else if (manageButtonVisible) {
+ } else {
await manageButton.click();
+ await page.locator('.contract-action-dropdown').waitFor({
+ state: 'visible',
+ timeout: 10000,
+ });
}
};
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/permission.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/permission.ts
index 6ed253c35e75..097fc1b21ecf 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/utils/permission.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/permission.ts
@@ -137,9 +137,12 @@ export const validateViewPermissions = async (
await expect(page.locator('[data-testid="add-domain"]')).not.toBeVisible();
if (permission?.editDisplayName) {
- expect(
- await page.locator('[data-testid="edit-displayName-button"]').count()
- ).toBeGreaterThan(0);
+ const editDisplayNameButton = page.locator(
+ '[data-testid="edit-displayName-button"]'
+ );
+ await expect(editDisplayNameButton.first()).toBeVisible({
+ timeout: 30_000,
+ });
} else {
await expect(
page.locator('[data-testid="edit-displayName-button"]')
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AppRouter.tsx
index 8fc8921459a3..a9f0cb69b9c1 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AppRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AppRouter.tsx
@@ -19,13 +19,13 @@ import { APP_ROUTER_ROUTES } from '../../constants/router.constants';
import { useApplicationStore } from '../../hooks/useApplicationStore';
import applicationRoutesClass from '../../utils/ApplicationRoutesClassBase';
import Loader from '../common/Loader/Loader';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
-const AuthenticatedApp = withSuspenseFallback(
+const AuthenticatedApp = withPageSuspenseFallback(
lazy(() => import('./AuthenticatedApp'))
);
-const AuthenticatedRoutes = withSuspenseFallback(
+const AuthenticatedRoutes = withPageSuspenseFallback(
lazy(() =>
import('./AuthenticatedRoutes').then((m) => ({
default: m.AuthenticatedRoutes,
@@ -34,11 +34,11 @@ const AuthenticatedRoutes = withSuspenseFallback(
);
// Lazy-load infrequently-visited unauthenticated pages
-const AccessNotAllowedPage = withSuspenseFallback(
+const AccessNotAllowedPage = withPageSuspenseFallback(
lazy(() => import('../../pages/AccessNotAllowedPage/AccessNotAllowedPage'))
);
-const LogoutPage = withSuspenseFallback(
+const LogoutPage = withPageSuspenseFallback(
lazy(() =>
import('../../pages/LogoutPage/LogoutPage').then((m) => ({
default: m.LogoutPage,
@@ -46,15 +46,15 @@ const LogoutPage = withSuspenseFallback(
)
);
-const PageNotFound = withSuspenseFallback(
+const PageNotFound = withPageSuspenseFallback(
lazy(() => import('../../pages/PageNotFound/PageNotFound'))
);
-const SamlCallback = withSuspenseFallback(
+const SamlCallback = withPageSuspenseFallback(
lazy(() => import('../../pages/SamlCallback'))
);
-const SignUpPage = withSuspenseFallback(
+const SignUpPage = withPageSuspenseFallback(
lazy(() => import('../../pages/SignUp/SignUpPage'))
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx
index 1063967aeb34..12386ee40996 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx
@@ -25,16 +25,16 @@ import { checkPermission, userPermissions } from '../../utils/PermissionsUtils';
import { useApplicationsProvider } from '../Settings/Applications/ApplicationsProvider/ApplicationsProvider';
import { RoutePosition } from '../Settings/Applications/plugins/AppPlugin';
import AdminProtectedRoute from './AdminProtectedRoute';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
// Previously statically imported — lazify so they stay out of the main chunk
-const AddCustomMetricPage = withSuspenseFallback(
+const AddCustomMetricPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/AddCustomMetricPage/AddCustomMetricPage')
)
);
-const CustomizablePage = withSuspenseFallback(
+const CustomizablePage = withPageSuspenseFallback(
React.lazy(() =>
import('../../pages/CustomizablePage/CustomizablePage').then((m) => ({
default: m.CustomizablePage,
@@ -42,74 +42,74 @@ const CustomizablePage = withSuspenseFallback(
)
);
-const DataQualityPage = withSuspenseFallback(
+const DataQualityPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/DataQuality/DataQualityPage'))
);
-const ForbiddenPage = withSuspenseFallback(
+const ForbiddenPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/ForbiddenPage/ForbiddenPage'))
);
-const PlatformLineage = withSuspenseFallback(
+const PlatformLineage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/PlatformLineage/PlatformLineage'))
);
-const TagPage = withSuspenseFallback(
+const TagPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/TagPage/TagPage'))
);
-const DomainRouter = withSuspenseFallback(
+const DomainRouter = withPageSuspenseFallback(
React.lazy(() => import('./DomainRouter'))
);
-const DataProductListPage = withSuspenseFallback(
+const DataProductListPage = withPageSuspenseFallback(
React.lazy(() => import('../DataProduct/DataProductListPage'))
);
-const SettingsRouter = withSuspenseFallback(
+const SettingsRouter = withPageSuspenseFallback(
React.lazy(() => import('./SettingsRouter'))
);
-const EntityRouter = withSuspenseFallback(
+const EntityRouter = withPageSuspenseFallback(
React.lazy(() => import('./EntityRouter'))
);
-const ClassificationRouter = withSuspenseFallback(
+const ClassificationRouter = withPageSuspenseFallback(
React.lazy(() => import('./ClassificationRouter'))
);
-const GlossaryRouter = withSuspenseFallback(
+const GlossaryRouter = withPageSuspenseFallback(
React.lazy(() => import('./GlossaryRouter/GlossaryRouter'))
);
-const GlossaryTermRouter = withSuspenseFallback(
+const GlossaryTermRouter = withPageSuspenseFallback(
React.lazy(() => import('./GlossaryTermRouter/GlossaryTermRouter'))
);
-const MyDataPage = withSuspenseFallback(
+const MyDataPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/MyDataPage/MyDataPage.component'))
);
-const TestSuiteIngestionPage = withSuspenseFallback(
+const TestSuiteIngestionPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/TestSuiteIngestionPage/TestSuiteIngestionPage')
)
);
-const TestSuiteDetailsPage = withSuspenseFallback(
+const TestSuiteDetailsPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component')
)
);
-const AddCustomProperty = withSuspenseFallback(
+const AddCustomProperty = withPageSuspenseFallback(
React.lazy(
() =>
import('../Settings/CustomProperty/AddCustomProperty/AddCustomProperty')
)
);
-const MarketPlacePage = withSuspenseFallback(
+const MarketPlacePage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/MarketPlacePage/MarketPlacePage'))
);
-const DataMarketplacePage = withSuspenseFallback(
+const DataMarketplacePage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -118,42 +118,42 @@ const DataMarketplacePage = withSuspenseFallback(
)
);
-const BotDetailsPage = withSuspenseFallback(
+const BotDetailsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/BotDetailsPage/BotDetailsPage'))
);
-const ServicePage = withSuspenseFallback(
+const ServicePage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/ServiceDetailsPage/ServiceDetailsPage'))
);
-const SwaggerPage = withSuspenseFallback(
+const SwaggerPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/SwaggerPage'))
);
-const TourPageComponent = withSuspenseFallback(
+const TourPageComponent = withPageSuspenseFallback(
React.lazy(() => import('../../pages/TourPage/TourPage.component'))
);
-const UserPage = withSuspenseFallback(
+const UserPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/UserPage/UserPage.component'))
);
-const DomainVersionPage = withSuspenseFallback(
+const DomainVersionPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../components/Domain/DomainVersion/DomainVersion.component')
)
);
-const AddIngestionPage = withSuspenseFallback(
+const AddIngestionPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/AddIngestionPage/AddIngestionPage.component')
)
);
-const AddServicePage = withSuspenseFallback(
+const AddServicePage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/AddServicePage/AddServicePage.component')
)
);
-const MarketPlaceAppDetails = withSuspenseFallback(
+const MarketPlaceAppDetails = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -162,11 +162,11 @@ const MarketPlaceAppDetails = withSuspenseFallback(
)
);
-const AppInstallPage = withSuspenseFallback(
+const AppInstallPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/AppInstall/AppInstall.component'))
);
-const EditConnectionFormPage = withSuspenseFallback(
+const EditConnectionFormPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -175,31 +175,31 @@ const EditConnectionFormPage = withSuspenseFallback(
)
);
-const CreateUserPage = withSuspenseFallback(
+const CreateUserPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/CreateUserPage/CreateUserPage.component')
)
);
-const EditIngestionPage = withSuspenseFallback(
+const EditIngestionPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/EditIngestionPage/EditIngestionPage.component')
)
);
-const ServiceVersionPage = withSuspenseFallback(
+const ServiceVersionPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/ServiceVersionPage/ServiceVersionPage'))
);
-const ExplorePageV1 = withSuspenseFallback(
+const ExplorePageV1 = withPageSuspenseFallback(
React.lazy(() => import('../../pages/ExplorePage/ExplorePageV1.component'))
);
-const OntologyExplorerPage = withSuspenseFallback(
+const OntologyExplorerPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/OntologyExplorerPage/OntologyExplorerPage')
)
);
-const RequestDescriptionPage = withSuspenseFallback(
+const RequestDescriptionPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -208,13 +208,13 @@ const RequestDescriptionPage = withSuspenseFallback(
)
);
-const RequestTagsPage = withSuspenseFallback(
+const RequestTagsPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/TasksPage/RequestTagPage/RequestTagPage')
)
);
-const UpdateDescriptionPage = withSuspenseFallback(
+const UpdateDescriptionPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -223,44 +223,44 @@ const UpdateDescriptionPage = withSuspenseFallback(
)
);
-const UpdateTagsPage = withSuspenseFallback(
+const UpdateTagsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/TasksPage/UpdateTagPage/UpdateTagPage'))
);
-const LogsViewerPage = withSuspenseFallback(
+const LogsViewerPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/LogsViewerPage/LogsViewerPage'))
);
-const DataInsightPage = withSuspenseFallback(
+const DataInsightPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/DataInsightPage/DataInsightPage.component')
)
);
-const AddKPIPage = withSuspenseFallback(
+const AddKPIPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/KPIPage/AddKPIPage'))
);
-const EditKPIPage = withSuspenseFallback(
+const EditKPIPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/KPIPage/EditKPIPage'))
);
-const QueryPage = withSuspenseFallback(
+const QueryPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/QueryPage/QueryPage.component'))
);
-const AddQueryPage = withSuspenseFallback(
+const AddQueryPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/AddQueryPage/AddQueryPage.component'))
);
-const IncidentManagerPage = withSuspenseFallback(
+const IncidentManagerPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/IncidentManager/IncidentManagerPage'))
);
-const TestLibraryPage = withSuspenseFallback(
+const TestLibraryPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/TestLibrary/TestLibraryPage'))
);
-const IncidentManagerDetailPage = withSuspenseFallback(
+const IncidentManagerDetailPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -269,41 +269,41 @@ const IncidentManagerDetailPage = withSuspenseFallback(
)
);
-const TestCaseVersionPage = withSuspenseFallback(
+const TestCaseVersionPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/TestCaseVersionPage/TestCaseVersionPage')
)
);
-const ObservabilityAlertsPage = withSuspenseFallback(
+const ObservabilityAlertsPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/ObservabilityAlertsPage/ObservabilityAlertsPage')
)
);
-const AlertDetailsPage = withSuspenseFallback(
+const AlertDetailsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/AlertDetailsPage/AlertDetailsPage'))
);
-const AddObservabilityPage = withSuspenseFallback(
+const AddObservabilityPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/AddObservabilityPage/AddObservabilityPage')
)
);
-const MetricListPage = withSuspenseFallback(
+const MetricListPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/MetricsPage/MetricListPage/MetricListPage')
)
);
-const AddMetricPage = withSuspenseFallback(
+const AddMetricPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/MetricsPage/AddMetricPage/AddMetricPage')
)
);
-const ColumnBulkOperationsPage = withSuspenseFallback(
+const ColumnBulkOperationsPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/ColumnBulkOperations/ColumnBulkOperations.component')
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedRoutes.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedRoutes.tsx
index 9bb196dc01f9..e6727104c74b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedRoutes.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedRoutes.tsx
@@ -20,13 +20,13 @@ import { useApplicationStore } from '../../hooks/useApplicationStore';
import AppContainer from '../AppContainer/AppContainer';
import { useApplicationsProvider } from '../Settings/Applications/ApplicationsProvider/ApplicationsProvider';
import { RoutePosition } from '../Settings/Applications/plugins/AppPlugin';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
-const PageNotFound = withSuspenseFallback(
+const PageNotFound = withPageSuspenseFallback(
lazy(() => import('../../pages/PageNotFound/PageNotFound'))
);
-const LogoutPage = withSuspenseFallback(
+const LogoutPage = withPageSuspenseFallback(
lazy(() =>
import('../../pages/LogoutPage/LogoutPage').then((module) => ({
default: module.LogoutPage,
@@ -34,15 +34,15 @@ const LogoutPage = withSuspenseFallback(
)
);
-const AccessNotAllowedPage = withSuspenseFallback(
+const AccessNotAllowedPage = withPageSuspenseFallback(
lazy(() => import('../../pages/AccessNotAllowedPage/AccessNotAllowedPage'))
);
-const SignUpPage = withSuspenseFallback(
+const SignUpPage = withPageSuspenseFallback(
lazy(() => import('../../pages/SignUp/SignUpPage'))
);
-const SamlCallback = withSuspenseFallback(
+const SamlCallback = withPageSuspenseFallback(
lazy(() => import('../../pages/SamlCallback'))
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityImportRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityImportRouter.tsx
index db0f485ee09d..7bc505522ae2 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityImportRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityImportRouter.tsx
@@ -19,9 +19,9 @@ import { ResourceEntity } from '../../context/PermissionProvider/PermissionProvi
import { useFqn } from '../../hooks/useFqn';
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
import { useRequiredParams } from '../../utils/useRequiredParams';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
-const BulkEntityImportPage = withSuspenseFallback(
+const BulkEntityImportPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityRouter.tsx
index 16ef1a8ce6b3..d1fb8a423819 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/EntityRouter.tsx
@@ -20,9 +20,9 @@ import { EntityType } from '../../enums/entity.enum';
import entityUtilClassBase from '../../utils/EntityUtilClassBase';
import { useRequiredParams } from '../../utils/useRequiredParams';
import EntityImportRouter from './EntityImportRouter';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
-const EntityVersionPage = withSuspenseFallback(
+const EntityVersionPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/EntityVersionPage/EntityVersionPage.component')
)
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx
index 8e90371eaafa..71c901123b74 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx
@@ -30,19 +30,19 @@ import {
getTeamsWithFqnPath,
} from '../../utils/RouterUtils';
import AdminProtectedRoute from './AdminProtectedRoute';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
-const AddNotificationPage = withSuspenseFallback(
+const AddNotificationPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/AddNotificationPage/AddNotificationPage')
)
);
-const AlertDetailsPage = withSuspenseFallback(
+const AlertDetailsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/AlertDetailsPage/AlertDetailsPage'))
);
-const AppearanceConfigSettingsPage = withSuspenseFallback(
+const AppearanceConfigSettingsPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -51,32 +51,32 @@ const AppearanceConfigSettingsPage = withSuspenseFallback(
)
);
-const ApplicationPage = withSuspenseFallback(
+const ApplicationPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/Application/ApplicationPage'))
);
-const AuditLogsPage = withSuspenseFallback(
+const AuditLogsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/AuditLogsPage/AuditLogsPage'))
);
-const BotsPageV1 = withSuspenseFallback(
+const BotsPageV1 = withPageSuspenseFallback(
React.lazy(() => import('../../pages/BotsPageV1/BotsPageV1.component'))
);
-const ColumnBulkOperations = withSuspenseFallback(
+const ColumnBulkOperations = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/ColumnBulkOperations/ColumnBulkOperations.component')
)
);
-const DataAssetRulesPage = withSuspenseFallback(
+const DataAssetRulesPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/Configuration/DataAssetRules/DataAssetRulesPage')
)
);
-const EditLoginConfiguration = withSuspenseFallback(
+const EditLoginConfiguration = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -85,7 +85,7 @@ const EditLoginConfiguration = withSuspenseFallback(
)
);
-const EditUrlConfigurationPage = withSuspenseFallback(
+const EditUrlConfigurationPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -94,7 +94,7 @@ const EditUrlConfigurationPage = withSuspenseFallback(
)
);
-const LoginConfigurationPage = withSuspenseFallback(
+const LoginConfigurationPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -103,27 +103,27 @@ const LoginConfigurationPage = withSuspenseFallback(
)
);
-const UrlConfigurationPage = withSuspenseFallback(
+const UrlConfigurationPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/Configuration/UrlConfiguration/UrlConfigurationPage')
)
);
-const CustomPropertiesPageV1 = withSuspenseFallback(
+const CustomPropertiesPageV1 = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/CustomPropertiesPageV1/CustomPropertiesPageV1')
)
);
-const EditEmailConfigPage = withSuspenseFallback(
+const EditEmailConfigPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/EditEmailConfigPage/EditEmailConfigPage.component')
)
);
-const EmailConfigSettingsPage = withSuspenseFallback(
+const EmailConfigSettingsPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -132,7 +132,7 @@ const EmailConfigSettingsPage = withSuspenseFallback(
)
);
-const GlobalSettingCategoryPage = withSuspenseFallback(
+const GlobalSettingCategoryPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -141,11 +141,11 @@ const GlobalSettingCategoryPage = withSuspenseFallback(
)
);
-const GlobalSettingPage = withSuspenseFallback(
+const GlobalSettingPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/GlobalSettingPage/GlobalSettingPage'))
);
-const GlossaryTermRelationSettingsPage = withSuspenseFallback(
+const GlossaryTermRelationSettingsPage = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -154,7 +154,7 @@ const GlossaryTermRelationSettingsPage = withSuspenseFallback(
)
);
-const LearningResourcesPage = withSuspenseFallback(
+const LearningResourcesPage = withPageSuspenseFallback(
React.lazy(() =>
import('../../pages/LearningResourcesPage/LearningResourcesPage').then(
(m) => ({ default: m.LearningResourcesPage })
@@ -162,25 +162,25 @@ const LearningResourcesPage = withSuspenseFallback(
)
);
-const LineageConfigPage = withSuspenseFallback(
+const LineageConfigPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/LineageConfigPage/LineageConfigPage'))
);
-const NotificationListPage = withSuspenseFallback(
+const NotificationListPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/NotificationListPage/NotificationListPage')
)
);
-const OmHealthPage = withSuspenseFallback(
+const OmHealthPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/OmHealth/OmHealthPage'))
);
-const OnlineUsersPage = withSuspenseFallback(
+const OnlineUsersPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/OnlineUsersPage/OnlineUsersPage'))
);
-const PersonaDetailsPage = withSuspenseFallback(
+const PersonaDetailsPage = withPageSuspenseFallback(
React.lazy(() =>
import('../../pages/Persona/PersonaDetailsPage/PersonaDetailsPage').then(
(m) => ({ default: m.PersonaDetailsPage })
@@ -188,7 +188,7 @@ const PersonaDetailsPage = withSuspenseFallback(
)
);
-const PersonaPage = withSuspenseFallback(
+const PersonaPage = withPageSuspenseFallback(
React.lazy(() =>
import('../../pages/Persona/PersonaListPage/PersonaPage').then((m) => ({
default: m.PersonaPage,
@@ -196,97 +196,97 @@ const PersonaPage = withSuspenseFallback(
)
);
-const AddPolicyPage = withSuspenseFallback(
+const AddPolicyPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/PoliciesPage/AddPolicyPage/AddPolicyPage')
)
);
-const AddRulePage = withSuspenseFallback(
+const AddRulePage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/PoliciesPage/PoliciesDetailPage/AddRulePage')
)
);
-const EditRulePage = withSuspenseFallback(
+const EditRulePage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/PoliciesPage/PoliciesDetailPage/EditRulePage')
)
);
-const PoliciesDetailPage = withSuspenseFallback(
+const PoliciesDetailPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage')
)
);
-const PoliciesListPage = withSuspenseFallback(
+const PoliciesListPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/PoliciesPage/PoliciesListPage/PoliciesListPage')
)
);
-const ProfilerConfigurationPage = withSuspenseFallback(
+const ProfilerConfigurationPage = withPageSuspenseFallback(
React.lazy(
() =>
import('../../pages/ProfilerConfigurationPage/ProfilerConfigurationPage')
)
);
-const AddRolePage = withSuspenseFallback(
+const AddRolePage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/RolesPage/AddRolePage/AddRolePage'))
);
-const RolesDetailPage = withSuspenseFallback(
+const RolesDetailPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/RolesPage/RolesDetailPage/RolesDetailPage')
)
);
-const RolesListPage = withSuspenseFallback(
+const RolesListPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/RolesPage/RolesListPage/RolesListPage'))
);
-const SearchSettingsPage = withSuspenseFallback(
+const SearchSettingsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/SearchSettingsPage/SearchSettingsPage'))
);
-const ServicesPage = withSuspenseFallback(
+const ServicesPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/ServicesPage/ServicesPage'))
);
-const IntakeFormsPage = withSuspenseFallback(
+const IntakeFormsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/IntakeForms/IntakeFormsPage'))
);
-const ImportTeamsPage = withSuspenseFallback(
+const ImportTeamsPage = withPageSuspenseFallback(
React.lazy(
() => import('../../pages/TeamsPage/ImportTeamsPage/ImportTeamsPage')
)
);
-const TeamsPage = withSuspenseFallback(
+const TeamsPage = withPageSuspenseFallback(
React.lazy(() => import('../../pages/TeamsPage/TeamsPage'))
);
-const UserListPageV1 = withSuspenseFallback(
+const UserListPageV1 = withPageSuspenseFallback(
React.lazy(() => import('../../pages/UserListPage/UserListPageV1'))
);
-const EntitySearchSettings = withSuspenseFallback(
+const EntitySearchSettings = withPageSuspenseFallback(
React.lazy(
() => import('../SearchSettings/EntitySeachSettings/EntitySearchSettings')
)
);
-const AppDetails = withSuspenseFallback(
+const AppDetails = withPageSuspenseFallback(
React.lazy(
() => import('../Settings/Applications/AppDetails/AppDetails.component')
)
);
-const AdminPermissionDebugger = withSuspenseFallback(
+const AdminPermissionDebugger = withPageSuspenseFallback(
React.lazy(
() =>
import(
@@ -295,7 +295,7 @@ const AdminPermissionDebugger = withSuspenseFallback(
)
);
-const SettingsSso = withSuspenseFallback(
+const SettingsSso = withPageSuspenseFallback(
React.lazy(() => import('../SettingsSso/SettingsSso'))
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/UnAuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/UnAuthenticatedAppRouter.tsx
index 1dc50b4ff6d1..9a82a524e315 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/UnAuthenticatedAppRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/UnAuthenticatedAppRouter.tsx
@@ -19,39 +19,39 @@ import { AuthProvider } from '../../generated/configuration/authenticationConfig
import { useApplicationStore } from '../../hooks/useApplicationStore';
import useCustomLocation from '../../hooks/useCustomLocation/useCustomLocation';
import applicationRoutesClass from '../../utils/ApplicationRoutesClassBase';
-import withSuspenseFallback from './withSuspenseFallback';
+import { withPageSuspenseFallback } from './withSuspenseFallback';
-const SigninPage = withSuspenseFallback(
+const SigninPage = withPageSuspenseFallback(
lazy(() => import('../../pages/LoginPage/SignInPage'))
);
-const ForgotPassword = withSuspenseFallback(
+const ForgotPassword = withPageSuspenseFallback(
lazy(() => import('../../pages/ForgotPassword/ForgotPassword.component'))
);
-const ResetPassword = withSuspenseFallback(
+const ResetPassword = withPageSuspenseFallback(
lazy(() => import('../../pages/ResetPassword/ResetPassword.component'))
);
-const BasicSignupPage = withSuspenseFallback(
+const BasicSignupPage = withPageSuspenseFallback(
lazy(() => import('../../pages/SignUp/BasicSignup.component'))
);
-const PageNotFound = withSuspenseFallback(
+const PageNotFound = withPageSuspenseFallback(
lazy(() => import('../../pages/PageNotFound/PageNotFound'))
);
-const AccountActivationConfirmation = withSuspenseFallback(
+const AccountActivationConfirmation = withPageSuspenseFallback(
lazy(
() => import('../../pages/SignUp/account-activation-confirmation.component')
)
);
-const Auth0Callback = withSuspenseFallback(
+const Auth0Callback = withPageSuspenseFallback(
lazy(() => import('../Auth/AppCallbacks/Auth0Callback/Auth0Callback'))
);
-const LoginCallback = withSuspenseFallback(
+const LoginCallback = withPageSuspenseFallback(
lazy(() =>
import('@okta/okta-react').then((m) => ({ default: m.LoginCallback }))
)
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.test.tsx
new file mode 100644
index 000000000000..ee04b6940d5c
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.test.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2026 Collate.
+ * Licensed 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 { render, screen } from '@testing-library/react';
+import { lazy } from 'react';
+import {
+ withPageSuspenseFallback,
+ withSuspenseFallback,
+} from './withSuspenseFallback';
+
+describe('withSuspenseFallback', () => {
+ const getLazyComponent = () =>
+ lazy(
+ () =>
+ new Promise<{ default: () => JSX.Element }>((resolve) => {
+ setTimeout(() => {
+ resolve({
+ default: () =>
Loaded component
,
+ });
+ }, 0);
+ })
+ );
+
+ it('does not render a default loading indicator while the chunk loads', () => {
+ const WrappedComponent = withSuspenseFallback(getLazyComponent());
+
+ render();
+
+ expect(screen.queryByTestId('loader')).not.toBeInTheDocument();
+ });
+
+ it('does not render a loading indicator when the caller opts into a silent fallback', () => {
+ const WrappedComponent = withSuspenseFallback(getLazyComponent(), null);
+
+ render();
+
+ expect(screen.queryByTestId('loader')).not.toBeInTheDocument();
+ });
+
+ it('renders an explicit fallback when the caller provides one', async () => {
+ const WrappedComponent = withSuspenseFallback(
+ getLazyComponent(),
+ Loading active route
+ );
+
+ render();
+
+ expect(screen.getByText('Loading active route')).toBeInTheDocument();
+ expect(await screen.findByText('Loaded component')).toBeInTheDocument();
+ });
+
+ it('renders the page loading indicator for route-level chunks', () => {
+ const WrappedComponent = withPageSuspenseFallback(getLazyComponent());
+
+ render();
+
+ expect(screen.getByTestId('loader')).toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.tsx
index 691eeaa37f04..4f021b5ac50b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/withSuspenseFallback.tsx
@@ -11,24 +11,29 @@
* limitations under the License.
*/
-import { ComponentType, forwardRef, Suspense } from 'react';
+import { ComponentType, forwardRef, ReactNode, Suspense } from 'react';
import Loader from '../common/Loader/Loader';
+export const TAB_CONTENT_FALLBACK = ;
+
export function withSuspenseFallback(
- Component: ComponentType
+ Component: ComponentType,
+ // Keep embedded/background lazy chunks silent unless a caller opts into visible progress.
+ fallback: ReactNode = null
) {
return forwardRef(function DefaultFallback(props, ref) {
return (
-
-
-
- }>
+
);
});
}
+export function withPageSuspenseFallback(
+ Component: ComponentType
+) {
+ return withSuspenseFallback(Component, );
+}
+
export default withSuspenseFallback;
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/LazyAuthProviderWrappers.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/LazyAuthProviderWrappers.tsx
index 137a4b58e5b2..0249e9fb27df 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/LazyAuthProviderWrappers.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/LazyAuthProviderWrappers.tsx
@@ -14,27 +14,28 @@
import type { CacheLocation } from '@auth0/auth0-react';
import type { IPublicClientApplication } from '@azure/msal-browser';
import { lazy, ReactNode } from 'react';
-import withSuspenseFallback from '../../AppRouter/withSuspenseFallback';
+import { withPageSuspenseFallback } from '../../AppRouter/withSuspenseFallback';
-const Auth0ProviderComponent = withSuspenseFallback(
+const Auth0ProviderComponent = withPageSuspenseFallback(
lazy(() =>
import('@auth0/auth0-react').then((m) => ({ default: m.Auth0Provider }))
)
);
-const MsalProviderComponent = withSuspenseFallback(
+const MsalProviderComponent = withPageSuspenseFallback(
lazy(() =>
import('@azure/msal-react').then((m) => ({ default: m.MsalProvider }))
)
);
-const OktaAuthProviderComponent = withSuspenseFallback(
+const OktaAuthProviderComponent = withPageSuspenseFallback(
lazy(() =>
import('./OktaAuthProvider').then((m) => ({ default: m.OktaAuthProvider }))
)
);
-const BasicAuthProviderComponent = withSuspenseFallback(
+// Auth providers wrap the app shell, so their cold chunks need a visible page fallback.
+const BasicAuthProviderComponent = withPageSuspenseFallback(
lazy(() => import('./BasicAuthProvider'))
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/CommonWidgets/CommonWidgets.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/CommonWidgets/CommonWidgets.tsx
index b3e6d58ec4a9..54f843493ff7 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/CommonWidgets/CommonWidgets.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/CommonWidgets/CommonWidgets.tsx
@@ -51,7 +51,9 @@ import {
import { getPrioritizedViewPermission } from '../../../utils/PermissionsUtils';
import { getTagsWithoutTier, getTierTags } from '../../../utils/TablePureUtils';
import { createTagObject } from '../../../utils/TagsPureUtils';
-import withSuspenseFallback from '../../AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../../AppRouter/withSuspenseFallback';
import CertificationWidget from '../../common/CertificationWidget/CertificationWidget';
import { CustomPropertyTable } from '../../common/CustomPropertyTable/CustomPropertyTable';
import DescriptionV1 from '../../common/EntityDescription/DescriptionV1';
@@ -65,12 +67,14 @@ import { DisplayType } from '../../Tag/TagsViewer/TagsViewer.interface';
import { DomainLabelV2 } from '../DomainLabelV2/DomainLabelV2';
import { OwnerLabelV2 } from '../OwnerLabelV2/OwnerLabelV2';
import { ReviewerLabelV2 } from '../ReviewerLabelV2/ReviewerLabelV2';
+
const GlossaryUpdateConfirmationModal = withSuspenseFallback(
lazy(() =>
import(
'../../Glossary/GlossaryUpdateConfirmationModal/GlossaryUpdateConfirmationModal'
).then((m) => ({ default: m.GlossaryUpdateConfirmationModal }))
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
interface GenericEntity
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DriveService/Directory/DirectoryDetails.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DriveService/Directory/DirectoryDetails.test.tsx
index a562568147a6..531a544a11df 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/DriveService/Directory/DirectoryDetails.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/DriveService/Directory/DirectoryDetails.test.tsx
@@ -79,9 +79,15 @@ jest.mock('../../common/CustomPropertyTable/CustomPropertyTable', () => ({
)),
}));
-jest.mock('../../common/Loader/Loader', () =>
- jest.fn(() => Loading...
)
-);
+jest.mock('../../common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loading...
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../Customization/GenericProvider/GenericProvider', () => ({
GenericProvider: jest.fn(({ children }) => (
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DriveService/File/FileDetails.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DriveService/File/FileDetails.test.tsx
index 6cdb07db1e12..5123b1e2b911 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/DriveService/File/FileDetails.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/DriveService/File/FileDetails.test.tsx
@@ -77,9 +77,15 @@ jest.mock('../../common/CustomPropertyTable/CustomPropertyTable', () => ({
)),
}));
-jest.mock('../../common/Loader/Loader', () =>
- jest.fn(() => Loading...
)
-);
+jest.mock('../../common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loading...
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../Customization/GenericProvider/GenericProvider', () => ({
GenericProvider: jest.fn(({ children }) => (
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeader/EntityHeader.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeader/EntityHeader.component.tsx
index 19bfcaf79c09..d29a43e261ba 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeader/EntityHeader.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeader/EntityHeader.component.tsx
@@ -12,16 +12,12 @@
*/
import classNames from 'classnames';
-import { lazy, ReactNode } from 'react';
+import { ReactNode } from 'react';
import { EntityType } from '../../../enums/entity.enum';
import { getEntityLinkFromType } from '../../../utils/EntityLinkUtils';
-import withSuspenseFallback from '../../AppRouter/withSuspenseFallback';
import TitleBreadcrumb from '../../common/TitleBreadcrumb/TitleBreadcrumb.component';
import { TitleBreadcrumbProps } from '../../common/TitleBreadcrumb/TitleBreadcrumb.interface';
-
-const EntityHeaderTitle = withSuspenseFallback(
- lazy(() => import('../EntityHeaderTitle/EntityHeaderTitle.component'))
-);
+import EntityHeaderTitle from '../EntityHeaderTitle/EntityHeaderTitle.component';
interface Props {
breadcrumb: TitleBreadcrumbProps['titleLinks'];
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MyData/Widgets/DataProductsWidget/DataProductsWidget.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MyData/Widgets/DataProductsWidget/DataProductsWidget.component.tsx
index f21fabe23039..c6e7ae953785 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/MyData/Widgets/DataProductsWidget/DataProductsWidget.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/MyData/Widgets/DataProductsWidget/DataProductsWidget.component.tsx
@@ -218,7 +218,7 @@ const DataProductsWidget = ({
),
- [dataProducts, isFullSize]
+ [assetsCounts, dataProducts, handleDataProductClick, isFullSize]
);
const showWidgetFooterMoreButton = useMemo(
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Pipeline/Execution/Execution.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Pipeline/Execution/Execution.component.tsx
index 7177da707110..c563ee07bee5 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Pipeline/Execution/Execution.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Pipeline/Execution/Execution.component.tsx
@@ -57,7 +57,7 @@ const ExecutionsTab = ({ pipelineFQN, tasks }: ExecutionProps) => {
const [endTime, setEndTime] = useState(getCurrentMillis());
const [isClickedCalendar, setIsClickedCalendar] = useState(false);
const [status, setStatus] = useState(MenuOptions.all);
- const [isLoading, setIsLoading] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
const fetchPipelineStatus = async (startRange: number, endRange: number) => {
try {
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx
index d080890f79af..fcbf608b7e14 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx
@@ -101,7 +101,7 @@ export const ApplicationsProvider = ({ children }: { children: ReactNode }) => {
return (
- {loading ? : children}
+ {loading ? : children}
);
};
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Topic/TopicSchema/TopicSchema.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Topic/TopicSchema/TopicSchema.tsx
index 7407a38f1a53..e29569ba9982 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Topic/TopicSchema/TopicSchema.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Topic/TopicSchema/TopicSchema.tsx
@@ -59,7 +59,9 @@ import {
} from '../../../utils/TablePureUtils';
import { getAllTags } from '../../../utils/TableTags/TableTags.utils';
import { getTableExpandableConfig } from '../../../utils/TableUtils';
-import withSuspenseFallback from '../../AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../../AppRouter/withSuspenseFallback';
import CopyLinkButton from '../../common/CopyLinkButton/CopyLinkButton';
import { EntityAttachmentProvider } from '../../common/EntityDescription/EntityAttachmentProvider/EntityAttachmentProvider';
import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
@@ -76,7 +78,8 @@ import {
} from './TopicSchema.interface';
const SchemaEditor = withSuspenseFallback(
- lazy(() => import('../../Database/SchemaEditor/SchemaEditor'))
+ lazy(() => import('../../Database/SchemaEditor/SchemaEditor')),
+ TAB_CONTENT_FALLBACK
);
const ModalWithMarkdownEditor = withSuspenseFallback(
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/Loader/Loader.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/Loader/Loader.tsx
index 778c8372a205..d2e5d2652b38 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/Loader/Loader.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/Loader/Loader.tsx
@@ -83,4 +83,12 @@ const Loader: FunctionComponent = ({
);
};
+// Use for blocking page-level loads only, so route and initial entity loaders
+// stay in the same position instead of jumping between bare spinner layouts.
+export const PageLoader = () => (
+
+
+
+);
+
export default Loader;
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/atoms/TagChip/TagChip.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/atoms/TagChip/TagChip.test.tsx
index bc96ca165fd4..434eb2fb386b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/atoms/TagChip/TagChip.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/atoms/TagChip/TagChip.test.tsx
@@ -13,6 +13,9 @@
import { render, screen } from '@testing-library/react';
import TagChip from './TagChip';
+// The global test setup stubs MUI styling; this suite needs real sx-generated CSS.
+jest.unmock('@mui/styled-engine');
+
jest.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key }),
}));
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.test.tsx
index 9f90476ebef0..486b2158498c 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.test.tsx
@@ -91,9 +91,11 @@ jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
jest.fn().mockImplementation(() => ErrorPlaceHolder
)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => Loader
),
+ PageLoader: jest.fn().mockImplementation(() => Loader
),
+}));
jest.mock('../../components/AppRouter/withActivityFeed', () => ({
withActivityFeed: jest.fn().mockImplementation((Component) => Component),
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx
index 1fca09c30d12..db1ab75fe4df 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx
@@ -27,7 +27,7 @@ import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { AlignRightIconButton } from '../../components/common/IconButtons/EditIconButton';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { GenericProvider } from '../../components/Customization/GenericProvider/GenericProvider';
import { DataAssetsHeader } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
@@ -499,7 +499,7 @@ const APICollectionPage: FunctionComponent = () => {
[tabs[0], tab]
);
if (isPermissionsLoading || isLoading) {
- return ;
+ return ;
}
if (!viewAPICollectionPermission) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx
index 5d8ba2c4b139..b518204b1b2b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import APIEndpointDetails from '../../components/APIEndpoint/APIEndpointDetails/APIEndpointDetails';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import { ROUTES } from '../../constants/constants';
@@ -264,7 +264,7 @@ const APIEndpointPage = () => {
}, [apiEndpointPermissions, apiEndpointFqn]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/AddServicePage/AddServicePage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/AddServicePage/AddServicePage.component.tsx
index 3c77154f0fb2..0188bc9b6967 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/AddServicePage/AddServicePage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/AddServicePage/AddServicePage.component.tsx
@@ -15,7 +15,7 @@ import { Space, Typography } from 'antd';
import { AxiosError } from 'axios';
import { isEmpty } from 'lodash';
import { LoadingState } from 'Models';
-import { useEffect, useMemo, useState } from 'react';
+import { Suspense, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ResizablePanels from '../../components/common/ResizablePanels/ResizablePanels';
@@ -335,11 +335,13 @@ const AddServicePage = () => {
pageTitle={t('label.add-entity', { entity: t('label.service') })}
secondPanel={{
children: (
-
+
+
+
),
className: 'service-doc-panel content-resizable-panel-container',
minWidth: 400,
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ChartDetailsPage/ChartDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ChartDetailsPage/ChartDetailsPage.component.tsx
index 6282e3f28908..9d944f2a1763 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/ChartDetailsPage/ChartDetailsPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/ChartDetailsPage/ChartDetailsPage.component.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ChartDetails from '../../components/Chart/ChartDetails/ChartDetails.component';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import { ROUTES } from '../../constants/constants';
@@ -253,7 +253,7 @@ const ChartDetailsPage = () => {
}, [chartFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.test.tsx
index 81cef1ac08f1..83096a554523 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.test.tsx
@@ -172,9 +172,15 @@ jest.mock('../../context/LineageProvider/LineageProvider', () =>
jest.fn().mockReturnValue(<>LineageProvider>)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockReturnValue(Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../components/PageLayoutV1/PageLayoutV1', () =>
jest.fn().mockImplementation(({ children }) => <>{children}>)
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx
index c693cf587497..e4125966f297 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx
@@ -18,7 +18,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import DashboardDetails from '../../components/Dashboard/DashboardDetails/DashboardDetails.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
@@ -277,7 +277,7 @@ const DashboardDetailsPage = () => {
}, [dashboardFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx
index 7717361ac90f..0ab5c8ec02d9 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx
@@ -18,7 +18,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import DataModelDetails from '../../components/Dashboard/DataModel/DataModels/DataModelDetails.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
@@ -292,7 +292,7 @@ const DataModelsPage = () => {
// Rendering
if (isLoading) {
- return ;
+ return ;
}
if (hasError) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.test.tsx
index 4e0036a4ee35..e8fa0ca24661 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.test.tsx
@@ -96,9 +96,15 @@ jest.mock(
)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../context/PermissionProvider/PermissionProvider', () => ({
usePermissionProvider: jest.fn().mockImplementation(() => ({
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx
index ff78ab2763a6..c3719dbcdbd9 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx
@@ -28,7 +28,7 @@ import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { AlignRightIconButton } from '../../components/common/IconButtons/EditIconButton';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { GenericProvider } from '../../components/Customization/GenericProvider/GenericProvider';
import { DataAssetsHeader } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
@@ -583,7 +583,7 @@ const DatabaseDetails: FunctionComponent = () => {
);
if (isLoading || isDatabaseDetailsLoading || loading) {
- return ;
+ return ;
}
if (!hasViewBasicPermission) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx
index 8b0699cf7cdd..d59b2a352fd5 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx
@@ -27,7 +27,7 @@ import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { AlignRightIconButton } from '../../components/common/IconButtons/EditIconButton';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { GenericProvider } from '../../components/Customization/GenericProvider/GenericProvider';
import { DataAssetsHeader } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
@@ -642,7 +642,7 @@ const DatabaseSchemaPage: FunctionComponent = () => {
}, [isFollowing, unFollowSchema, followSchema]);
if (isPermissionsLoading) {
- return ;
+ return ;
}
if (!viewDatabaseSchemaPermission) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.test.tsx
index c608cb4dfbfa..a545d8aa3f42 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.test.tsx
@@ -157,9 +157,15 @@ jest.mock('../../utils/ToastUtils', () => ({
.mockImplementation(({ children }) => {children}
),
}));
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => testLoader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
jest.fn().mockImplementation(() => ErrorPlaceHolder
)
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.test.tsx
index 3fe4f332bf69..bb1fc97de578 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.test.tsx
@@ -212,9 +212,15 @@ jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../components/AppRouter/withActivityFeed', () => ({
withActivityFeed: jest.fn().mockImplementation((Component) => Component),
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.tsx
index 26da40aafe64..258d26fc6dbf 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/DirectoryDetailsPage/DirectoryDetailsPage.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import DirectoryDetails from '../../components/DriveService/Directory/DirectoryDetails';
@@ -283,7 +283,7 @@ const DirectoryDetailsPage = () => {
}, [directoryPermissions, directoryFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/EditConnectionFormPage/EditConnectionFormPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/EditConnectionFormPage/EditConnectionFormPage.component.tsx
index 0651738845c2..25fd6362898e 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/EditConnectionFormPage/EditConnectionFormPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/EditConnectionFormPage/EditConnectionFormPage.component.tsx
@@ -16,7 +16,7 @@ import { AxiosError } from 'axios';
import { compare } from 'fast-json-patch';
import { isEmpty, isUndefined, startCase } from 'lodash';
import { LoadingState, ServicesUpdateRequest, ServiceTypes } from 'Models';
-import { useEffect, useMemo, useState } from 'react';
+import { Suspense, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
@@ -293,11 +293,13 @@ function EditConnectionFormPage() {
pageTitle={t('label.edit-entity', { entity: t('label.connection') })}
secondPanel={{
children: (
-
+
+
+
),
className: 'service-doc-panel content-resizable-panel-container',
minWidth: 400,
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.test.tsx
index fd74dc71dc52..ad9b512a18fc 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.test.tsx
@@ -204,9 +204,15 @@ jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../components/AppRouter/withActivityFeed', () => ({
withActivityFeed: jest.fn().mockImplementation((Component) => Component),
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.tsx
index dffaee366875..a3e094f19139 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/FileDetailsPage/FileDetailsPage.tsx
@@ -18,7 +18,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import FileDetails from '../../components/DriveService/File/FileDetails';
@@ -260,7 +260,7 @@ function FileDetailsPage() {
}, [filePermissions, fileFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.test.tsx
index 5a8e50a702a8..cbc7faced7c3 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.test.tsx
@@ -129,9 +129,15 @@ jest.mock('../../../components/PageLayoutV1/PageLayoutV1', () =>
{children}
))
);
-jest.mock('../../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock(
'../../../components/DataQuality/IncidentManager/IncidentManagerPageHeader/IncidentManagerPageHeader.component',
() => jest.fn().mockImplementation(() => IncidentManagerPageHeader
)
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx
index be0e8d6488fd..28dc9a8ddc1f 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx
@@ -28,7 +28,7 @@ import { BetaBadge } from '../../../components/common/Badge/Badge.component';
import ManageButton from '../../../components/common/EntityPageInfos/ManageButton/ManageButton';
import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { AlignRightIconButton } from '../../../components/common/IconButtons/EditIconButton';
-import Loader from '../../../components/common/Loader/Loader';
+import { PageLoader } from '../../../components/common/Loader/Loader';
import { ManageButtonItemLabel } from '../../../components/common/ManageButtonContentItem/ManageButtonContentItem.component';
import TitleBreadcrumb from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
import { TitleBreadcrumbProps } from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.interface';
@@ -412,7 +412,7 @@ const IncidentManagerDetailPage = ({
}, [t, hasEditPermission, isVersionPage, testCase?.entityLink]);
if (isLoading || isPermissionLoading) {
- return ;
+ return ;
}
if (!hasViewPermission) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricDetailsPage/MetricDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricDetailsPage/MetricDetailsPage.tsx
index 783eb9ce5f61..72017f95cf1c 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricDetailsPage/MetricDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricDetailsPage/MetricDetailsPage.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../../components/common/Loader/Loader';
+import { PageLoader } from '../../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../../components/Database/TableQueries/TableQueries.interface';
import MetricDetails from '../../../components/Metric/MetricDetails/MetricDetails';
@@ -268,7 +268,7 @@ const MetricDetailsPage = () => {
}, [metricPermissions, metricFqn]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx
index 945df303a0d2..a478895e053c 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx
@@ -18,7 +18,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import MlModelDetailComponent from '../../components/MlModel/MlModelDetail/MlModelDetail.component';
@@ -296,7 +296,7 @@ const MlModelPage = () => {
}, [mlModelFqn]);
if (isDetailLoading) {
- return ;
+ return ;
}
if (isNil(mlModelDetail) || isEmpty(mlModelDetail)) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx
index fc9406dde8be..d452e16a0eea 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx
@@ -18,7 +18,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import PipelineDetails from '../../components/Pipeline/PipelineDetails/PipelineDetails.component';
@@ -342,7 +342,7 @@ const PipelineDetailsPage = () => {
}, [decodedPipelineFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.test.tsx
index 5ae487ba0a6b..6f488d3bc921 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.test.tsx
@@ -115,9 +115,13 @@ jest.mock('react-router-dom', () => ({
useLocation: jest.fn().mockImplementation(() => ({ pathname: 'mockPath' })),
}));
-jest.mock('../../components/common/Loader/Loader', () => {
- return jest.fn().mockImplementation(() => <>testLoader>);
-});
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => <>testLoader>),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('./SearchIndexFieldsTab/SearchIndexFieldsTab', () => {
return jest.fn().mockImplementation(() => testSearchIndexFieldsTab
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.tsx
index d6e3d4b56db8..2fe4a425483c 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexDetailsPage.tsx
@@ -22,7 +22,7 @@ import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { AlignRightIconButton } from '../../components/common/IconButtons/EditIconButton';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { GenericProvider } from '../../components/Customization/GenericProvider/GenericProvider';
import { DataAssetsHeader } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
@@ -568,7 +568,7 @@ function SearchIndexDetailsPage() {
[tabs[0], activeTab]
);
if (isLoading || loading) {
- return ;
+ return ;
}
if (!viewPermission) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexFieldsTab/SearchIndexFieldsTab.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexFieldsTab/SearchIndexFieldsTab.tsx
index 25a2c2016439..1c8f0bc43a72 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexFieldsTab/SearchIndexFieldsTab.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/SearchIndexDetailsPage/SearchIndexFieldsTab/SearchIndexFieldsTab.tsx
@@ -12,7 +12,9 @@
*/
import { lazy, useCallback, useMemo } from 'react';
-import withSuspenseFallback from '../../../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../../../components/AppRouter/withSuspenseFallback';
import { useGenericContext } from '../../../components/Customization/GenericProvider/GenericContext';
import {
SearchIndex,
@@ -22,7 +24,8 @@ import { useFqn } from '../../../hooks/useFqn';
import { getAllRowKeysByKeyName } from '../../../utils/TablePureUtils';
const SearchIndexFieldsTable = withSuspenseFallback(
- lazy(() => import('../SearchIndexFieldsTable/SearchIndexFieldsTable'))
+ lazy(() => import('../SearchIndexFieldsTable/SearchIndexFieldsTable')),
+ TAB_CONTENT_FALLBACK
);
function SearchIndexFieldsTab() {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.test.tsx
index 37d74985dcab..2ab6c111a054 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.test.tsx
@@ -439,9 +439,15 @@ jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
))
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
// Additional missing component mocks
jest.mock(
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.tsx
index c6e484223f73..269f0fad48af 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/ServiceDetailsPage/ServiceDetailsPage.tsx
@@ -33,7 +33,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import AirflowMessageBanner from '../../components/common/AirflowMessageBanner/AirflowMessageBanner';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { PagingHandlerParams } from '../../components/common/NextPrevious/NextPrevious.interface';
import TabsLabel from '../../components/common/TabsLabel/TabsLabel.component';
import TestConnection from '../../components/common/TestConnection/TestConnection';
@@ -1944,7 +1944,7 @@ const ServiceDetailsPage: FunctionComponent = () => {
}, []);
if (isLoading) {
- return ;
+ return ;
}
if (!(servicePermission.ViewAll || servicePermission.ViewBasic)) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.test.tsx
index 81428722667a..ed257db04abc 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.test.tsx
@@ -211,9 +211,15 @@ jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../components/AppRouter/withActivityFeed', () => ({
withActivityFeed: jest.fn().mockImplementation((Component) => Component),
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.tsx
index cee4b9711d93..7b5045a43c16 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/SpreadsheetDetailsPage/SpreadsheetDetailsPage.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import SpreadsheetDetails from '../../components/DriveService/Spreadsheet/SpreadsheetDetails';
@@ -287,7 +287,7 @@ const SpreadsheetDetailsPage = () => {
}, [spreadsheetPermissions, spreadsheetFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.test.tsx
index 59a96a08e214..a0bb15189975 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.test.tsx
@@ -135,9 +135,13 @@ jest.mock('react-router-dom', () => ({
useLocation: jest.fn().mockImplementation(() => ({ pathname: 'mockPath' })),
}));
-jest.mock('../../components/common/Loader/Loader', () => {
- return jest.fn().mockImplementation(() => <>testLoader>);
-});
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => <>testLoader>),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../hoc/LimitWrapper', () => {
return jest.fn().mockImplementation(({ children }) => {children}
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx
index b606f04b9079..fae4946f7bf0 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx
@@ -19,7 +19,7 @@ import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { AlignRightIconButton } from '../../components/common/IconButtons/EditIconButton';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { GenericProvider } from '../../components/Customization/GenericProvider/GenericProvider';
import { DataAssetsHeader } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
@@ -562,7 +562,7 @@ const StoredProcedurePage = () => {
}, [decodedStoredProcedureFQN, storedProcedurePermissions]);
if (isLoading || loading) {
- return ;
+ return ;
}
if (!viewBasicPermission) {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedureTab.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedureTab.tsx
index f1c21d59c1b4..f12f8e3cf46e 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedureTab.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedureTab.tsx
@@ -57,7 +57,7 @@ const StoredProcedureTab = () => {
} = usePaging();
const [storedProcedure, setStoredProcedure] = useState([]);
- const [isLoading, setIsLoading] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
const { fqn: decodedDatabaseSchemaFQN } = useFqn();
useEffect(() => {
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx
index d0c75308c9b7..8e1963e73ce7 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx
@@ -300,9 +300,13 @@ jest.mock('../../context/TourProvider/TourProvider', () => ({
})),
}));
-jest.mock('../../components/common/Loader/Loader', () => {
- return jest.fn().mockImplementation(() => <>testLoader>);
-});
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => <>testLoader>),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.useFakeTimers();
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx
index 12af41ed90e9..4b3631701206 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx
@@ -18,7 +18,7 @@ import { FunctionComponent, useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import TopicDetails from '../../components/Topic/TopicDetails/TopicDetails.component';
@@ -262,7 +262,7 @@ const TopicDetailsPage: FunctionComponent = () => {
}, [topicPermissions, topicFQN]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.test.tsx
index 9ef016d8c8a6..e1724223f0ee 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.test.tsx
@@ -215,9 +215,15 @@ jest.mock('../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
)
);
-jest.mock('../../components/common/Loader/Loader', () =>
- jest.fn().mockImplementation(() => Loader
)
-);
+jest.mock('../../components/common/Loader/Loader', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+ PageLoader: jest
+ .fn()
+ .mockImplementation(() => Loader
),
+}));
jest.mock('../../components/AppRouter/withActivityFeed', () => ({
withActivityFeed: jest.fn().mockImplementation((Component) => Component),
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.tsx
index a80493ba8a5d..bbfccd284940 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/WorksheetDetailsPage/WorksheetDetailsPage.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../../components/common/Loader/Loader';
+import { PageLoader } from '../../components/common/Loader/Loader';
import { DataAssetWithDomains } from '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface';
import WorksheetDetails from '../../components/DriveService/Worksheet/WorksheetDetails';
@@ -324,7 +324,7 @@ const WorksheetDetailsPage = () => {
}, [decodedWorksheetFQN, resolvedEntityFqn]);
if (isLoading) {
- return ;
+ return ;
}
if (isError) {
return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/test/unit/mocks/withSuspenseFallback.mock.tsx b/openmetadata-ui/src/main/resources/ui/src/test/unit/mocks/withSuspenseFallback.mock.tsx
index d3c5cf1832e9..f509454accb6 100644
--- a/openmetadata-ui/src/main/resources/ui/src/test/unit/mocks/withSuspenseFallback.mock.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/test/unit/mocks/withSuspenseFallback.mock.tsx
@@ -30,4 +30,8 @@ export function withSuspenseFallback(
});
}
+// Route-level chunks use a visible fallback in production, but unit tests keep
+// the mock silent to avoid unrelated loader assertions across router tests.
+export const withPageSuspenseFallback = withSuspenseFallback;
+
export default withSuspenseFallback;
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.test.ts b/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.test.ts
index 39db2517477e..7823f79a64e1 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.test.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.test.ts
@@ -18,6 +18,10 @@ import applicationRoutesClassBase, {
ApplicationRoutesClassBase,
} from './ApplicationRoutesClassBase';
+jest.mock('../components/AppRouter/UnAuthenticatedAppRouter', () => ({
+ UnAuthenticatedAppRouter: jest.fn(),
+}));
+
jest.mock('../components/AppRouter/AuthenticatedAppRouter', () => ({
__esModule: true,
default: function AuthenticatedAppRouter() {
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.ts b/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.ts
index cf8250ab69d6..86a54705c607 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/ApplicationRoutesClassBase.ts
@@ -13,10 +13,10 @@
import { FC, lazy } from 'react';
import { UnAuthenticatedAppRouter } from '../components/AppRouter/UnAuthenticatedAppRouter';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import { withPageSuspenseFallback } from '../components/AppRouter/withSuspenseFallback';
import { UNPROTECTED_ROUTES } from '../constants/router.constants';
-const AuthenticatedAppRouter = withSuspenseFallback(
+const AuthenticatedAppRouter = withPageSuspenseFallback(
lazy(() => import('../components/AppRouter/AuthenticatedAppRouter'))
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.test.ts b/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.test.ts
index 4f1b5cabb1c7..da3d18d88993 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.test.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.test.ts
@@ -19,7 +19,6 @@ import {
import { AuthProvider } from '../generated/settings/settings';
import {
getAuthConfig,
- getCandidateUserManagerConfig,
getUserManagerConfig,
} from './AuthProvider.util';
@@ -127,13 +126,3 @@ describe('getAuthConfig — every OIDC provider respects the server-provided res
expect(config.responseType).toBe('code');
});
});
-
-describe('getCandidateUserManagerConfig — SSO test-login popup respects responseType', () => {
- it('should use the configured response_type instead of a hardcoded "id_token"', () => {
- const config = getCandidateUserManagerConfig(
- withScope({ responseType: ResponseType.Code })
- );
-
- expect(config.response_type).toBe('code');
- });
-});
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.test.tsx
index 3f3fa721365e..1417e6407787 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.test.tsx
@@ -10,6 +10,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import { render, screen } from '@testing-library/react';
+import { lazy } from 'react';
import { mockWidget } from '../mocks/AddWidgetTabContent.mock';
import { mockCurrentAddWidget } from '../mocks/CustomizablePage.mock';
import {
@@ -22,8 +24,95 @@ import {
getUniqueFilteredLayout,
getWidgetWidthLabelFromKey,
} from './CustomizableLandingPagePureUtils';
+import { getWidgetFromKey } from './CustomizableLandingPageUtils';
+import customizeMyDataPageClassBase from './CustomizeMyDataPageClassBase';
+
+jest.mock(
+ '../components/MyData/Widgets/Common/WidgetWrapper/WidgetWrapper',
+ () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(({ children, loading }) => (
+
+ {children}
+
+ )),
+ })
+);
describe('CustomizableLandingPageUtils', () => {
+ describe('getWidgetFromKey', () => {
+ // Keep the lazy component pending so each assertion observes the Suspense fallback.
+ const PendingWidget = lazy(() => new Promise(() => undefined));
+
+ beforeEach(() => {
+ jest
+ .spyOn(customizeMyDataPageClassBase, 'getWidgetsFromKey')
+ .mockReturnValue(PendingWidget);
+ });
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('should render normal widget chunks without a per-widget loader', () => {
+ const { container } = render(
+ getWidgetFromKey({
+ widgetConfig: {
+ h: 3,
+ i: 'KnowledgePanel.ActivityFeed',
+ static: false,
+ w: 1,
+ x: 0,
+ y: 0,
+ },
+ })
+ );
+
+ expect(screen.queryByTestId('widget-wrapper')).not.toBeInTheDocument();
+ expect(container).toBeEmptyDOMElement();
+ });
+
+ it('should preserve widget slots while edit-mode chunks load', () => {
+ render(
+ getWidgetFromKey({
+ isEditView: true,
+ widgetConfig: {
+ h: 3,
+ i: 'KnowledgePanel.ActivityFeed',
+ static: false,
+ w: 1,
+ x: 0,
+ y: 0,
+ },
+ })
+ );
+
+ expect(screen.getByTestId('widget-wrapper')).toHaveAttribute(
+ 'data-loading',
+ 'true'
+ );
+ });
+
+ it('should render empty placeholders immediately', () => {
+ render(
+ getWidgetFromKey({
+ handleOpenAddWidgetModal: jest.fn(),
+ handlePlaceholderWidgetKey: jest.fn(),
+ widgetConfig: {
+ h: 3,
+ i: 'ExtraWidget.EmptyWidgetPlaceholder',
+ static: false,
+ w: 1,
+ x: 0,
+ y: 0,
+ },
+ })
+ );
+
+ expect(screen.getByTestId('add-widget-button')).toBeInTheDocument();
+ });
+ });
+
describe('getNewWidgetPlacement', () => {
it('should place widget in same row if space available', () => {
const currentLayout = [
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.tsx
index d0d43add46a5..d5c56f06b861 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/CustomizableLandingPageUtils.tsx
@@ -60,9 +60,14 @@ export const getWidgetFromKey = ({
}
const Widget = customizeMyDataPageClassBase.getWidgetsFromKey(widgetConfig.i);
+ // Normal My Data keeps lazy widget chunks silent; edit mode preserves grid slots
+ // because disappearing cells are more disruptive while arranging widgets.
+ const fallback = isEditView ? (
+ {null}
+ ) : null;
return (
- {null}}>
+
({
default: module.InputOutputPortsTab,
}))
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const ResizablePanels = withSuspenseFallback(
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseSchemaTabsUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseSchemaTabsUtils.tsx
index 08a95ce9ce67..44ed78be3c48 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseSchemaTabsUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseSchemaTabsUtils.tsx
@@ -13,7 +13,9 @@
import { get } from 'lodash';
import { lazy } from 'react';
import { ActivityFeedLayoutType } from '../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../components/AppRouter/withSuspenseFallback';
import type {
CustomPropertyProps,
ExtentionEntitiesKeys,
@@ -56,11 +58,13 @@ const ContractTab = withSuspenseFallback(
);
const SchemaTablesTab = withSuspenseFallback(
- lazy(() => import('../pages/DatabaseSchemaPage/SchemaTablesTab'))
+ lazy(() => import('../pages/DatabaseSchemaPage/SchemaTablesTab')),
+ TAB_CONTENT_FALLBACK
);
const StoredProcedureTab = withSuspenseFallback(
- lazy(() => import('../pages/StoredProcedure/StoredProcedureTab'))
+ lazy(() => import('../pages/StoredProcedure/StoredProcedureTab')),
+ TAB_CONTENT_FALLBACK
);
export const getDataBaseSchemaPageBaseTabs = ({
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DirectoryDetailsUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/DirectoryDetailsUtils.tsx
index 80196b165f8e..590cad07504d 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/DirectoryDetailsUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/DirectoryDetailsUtils.tsx
@@ -13,7 +13,9 @@
import { get } from 'lodash';
import { lazy } from 'react';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../components/AppRouter/withSuspenseFallback';
import TabsLabel from '../components/common/TabsLabel/TabsLabel.component';
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
@@ -37,7 +39,8 @@ const DirectoryChildrenTable = withSuspenseFallback(
import(
'../components/DriveService/Directory/DirectoryChildrenTable/DirectoryChildrenTable'
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
export interface DirectoryDetailPageTabProps {
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityDetailComponentUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityDetailComponentUtils.tsx
index 04418d7de24c..80095688f8ca 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityDetailComponentUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityDetailComponentUtils.tsx
@@ -12,6 +12,7 @@
*/
import { ComponentType, FC, lazy, LazyExoticComponent, Suspense } from 'react';
+import Loader from '../components/common/Loader/Loader';
import { EntityType } from '../enums/entity.enum';
const lazyComponentMap: Partial<
@@ -90,7 +91,7 @@ export function getEntityDetailComponent(entityType: string): FC | null {
}
const WrappedComponent: FC = (props) => (
-
+ }>
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/FileDetailsUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/FileDetailsUtils.tsx
index 91f2d7d270f5..2cd4a4e15a41 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/FileDetailsUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/FileDetailsUtils.tsx
@@ -13,7 +13,9 @@
import { get, isEmpty } from 'lodash';
import { lazy } from 'react';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../components/AppRouter/withSuspenseFallback';
import TabsLabel from '../components/common/TabsLabel/TabsLabel.component';
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
@@ -37,7 +39,8 @@ const FileColumnsTable = withSuspenseFallback(
import(
'../components/DriveService/File/FileColumnsTable/FileColumnsTable'
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
export interface FileDetailPageTabProps {
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/LazyTagComponents.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/LazyTagComponents.tsx
index 08bc13c24728..968e3aadad69 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/LazyTagComponents.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/LazyTagComponents.tsx
@@ -12,6 +12,7 @@
*/
import { lazy, Suspense } from 'react';
+import { TAB_CONTENT_FALLBACK } from '../components/AppRouter/withSuspenseFallback';
import { DomainLabelProps } from '../components/common/DomainLabel/DomainLabel.interface';
import { OwnerLabelV2Props } from '../components/DataAssets/OwnerLabelV2/OwnerLabelV2';
import { EntityType } from '../enums/entity.enum';
@@ -42,7 +43,7 @@ interface LazyCommonWidgetsProps {
}
export const LazyCommonWidgets = (props: LazyCommonWidgetsProps) => (
-
+
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/PipelineDetailsUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/PipelineDetailsUtils.tsx
index 12e4ad76d392..17622137cc55 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/PipelineDetailsUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/PipelineDetailsUtils.tsx
@@ -17,7 +17,9 @@ import { ReactComponent as IconFailBadge } from '../assets/svg/fail-badge.svg';
import { ReactComponent as IconSkippedBadge } from '../assets/svg/skipped-badge.svg';
import { ReactComponent as IconSuccessBadge } from '../assets/svg/success-badge.svg';
import { ActivityFeedLayoutType } from '../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../components/AppRouter/withSuspenseFallback';
import type {
CustomPropertyProps,
ExtentionEntitiesKeys,
@@ -75,7 +77,8 @@ const EntityLineageTab = withSuspenseFallback(
);
const ExecutionsTab = withSuspenseFallback(
- lazy(() => import('../components/Pipeline/Execution/Execution.component'))
+ lazy(() => import('../components/Pipeline/Execution/Execution.component')),
+ TAB_CONTENT_FALLBACK
);
const PipelineTaskTab = withSuspenseFallback(
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/SearchIndexUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/SearchIndexUtils.tsx
index d9cad5bdffe5..25ad9920a06b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/SearchIndexUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/SearchIndexUtils.tsx
@@ -14,13 +14,14 @@
import { get, uniqueId } from 'lodash';
import { lazy, Suspense } from 'react';
import { ActivityFeedLayoutType } from '../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../components/AppRouter/withSuspenseFallback';
import type {
CustomPropertyProps,
ExtentionEntitiesKeys,
} from '../components/common/CustomPropertyTable/CustomPropertyTable.interface';
import ErrorPlaceHolder from '../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
-import Loader from '../components/common/Loader/Loader';
import TabsLabel from '../components/common/TabsLabel/TabsLabel.component';
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
@@ -63,7 +64,8 @@ const ContractTab = withSuspenseFallback(
)
);
const QueryViewer = withSuspenseFallback(
- lazy(() => import('../components/common/QueryViewer/QueryViewer.component'))
+ lazy(() => import('../components/common/QueryViewer/QueryViewer.component')),
+ TAB_CONTENT_FALLBACK
);
const SampleDataWithMessages = withSuspenseFallback(
lazy(
@@ -71,7 +73,8 @@ const SampleDataWithMessages = withSuspenseFallback(
import(
'../components/Database/SampleDataWithMessages/SampleDataWithMessages'
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const SearchIndexFieldsTab = withSuspenseFallback(
lazy(
@@ -79,7 +82,8 @@ const SearchIndexFieldsTab = withSuspenseFallback(
import(
'../pages/SearchIndexDetailsPage/SearchIndexFieldsTab/SearchIndexFieldsTab'
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const EntityLineageTab = lazy(() =>
import('../components/Lineage/EntityLineageTab/EntityLineageTab').then(
@@ -186,7 +190,7 @@ export const getSearchIndexDetailsTabs = ({
),
key: EntityTabs.LINEAGE,
children: (
- }>
+
({ default: module.ActivityFeedTab }))
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const ErrorPlaceHolder = withSuspenseFallback(
lazy(
() => import('../components/common/ErrorWithPlaceholder/ErrorPlaceHolder')
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const GenericTab = withSuspenseFallback(
@@ -56,7 +59,8 @@ const GenericTab = withSuspenseFallback(
import('../components/Customization/GenericTab/GenericTab').then(
(module) => ({ default: module.GenericTab })
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const CommonWidgets = withSuspenseFallback(
@@ -64,7 +68,8 @@ const CommonWidgets = withSuspenseFallback(
import('../components/DataAssets/CommonWidgets/CommonWidgets').then(
(module) => ({ default: module.CommonWidgets })
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const CustomPropertyTable = withSuspenseFallback(
@@ -72,24 +77,30 @@ const CustomPropertyTable = withSuspenseFallback(
import('../components/common/CustomPropertyTable/CustomPropertyTable').then(
(module) => ({ default: module.CustomPropertyTable })
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
) as (
props: CustomPropertyProps
) => JSX.Element;
const SchemaTable = withSuspenseFallback(
- lazy(() => import('../components/Database/SchemaTable/SchemaTable.component'))
+ lazy(
+ () => import('../components/Database/SchemaTable/SchemaTable.component')
+ ),
+ TAB_CONTENT_FALLBACK
);
const SampleDataTableComponent = withSuspenseFallback(
lazy(
() =>
import('../components/Database/SampleDataTable/SampleDataTable.component')
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const TableQueries = withSuspenseFallback(
- lazy(() => import('../components/Database/TableQueries/TableQueries'))
+ lazy(() => import('../components/Database/TableQueries/TableQueries')),
+ TAB_CONTENT_FALLBACK
);
const ContractTab = withSuspenseFallback(
@@ -97,7 +108,8 @@ const ContractTab = withSuspenseFallback(
import('../components/DataContract/ContractTab/ContractTab').then(
(module) => ({ default: module.ContractTab })
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const DataObservabilityTab = withSuspenseFallback(
@@ -106,7 +118,8 @@ const DataObservabilityTab = withSuspenseFallback(
import(
'../components/Database/Profiler/DataObservability/DataObservabilityTab'
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const EntityLineageTab = withSuspenseFallback(
@@ -114,22 +127,26 @@ const EntityLineageTab = withSuspenseFallback(
import('../components/Lineage/EntityLineageTab/EntityLineageTab').then(
(module) => ({ default: module.EntityLineageTab })
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const TableConstraints = withSuspenseFallback(
lazy(
() =>
import('../pages/TableDetailsPageV1/TableConstraints/TableConstraints')
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const KnowledgeGraph = withSuspenseFallback(
- lazy(() => import('../components/KnowledgeGraph/KnowledgeGraph'))
+ lazy(() => import('../components/KnowledgeGraph/KnowledgeGraph')),
+ TAB_CONTENT_FALLBACK
);
const QueryViewer = withSuspenseFallback(
- lazy(() => import('../components/common/QueryViewer/QueryViewer.component'))
+ lazy(() => import('../components/common/QueryViewer/QueryViewer.component')),
+ TAB_CONTENT_FALLBACK
);
const FrequentlyJoinedTables = withSuspenseFallback(
@@ -137,7 +154,8 @@ const FrequentlyJoinedTables = withSuspenseFallback(
import(
'../pages/TableDetailsPageV1/FrequentlyJoinedTables/FrequentlyJoinedTables.component'
).then((module) => ({ default: module.FrequentlyJoinedTables }))
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const PartitionedKeys = withSuspenseFallback(
@@ -145,7 +163,8 @@ const PartitionedKeys = withSuspenseFallback(
import(
'../pages/TableDetailsPageV1/PartitionedKeys/PartitionedKeys.component'
).then((module) => ({ default: module.PartitionedKeys }))
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
export const getTableDetailPageBaseTabs = ({
@@ -295,7 +314,7 @@ export const getTableDetailPageBaseTabs = ({
),
key: EntityTabs.LINEAGE,
children: (
- }>
+
}>
+
({ default: module.GenericTab })
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
const CommonWidgets = withSuspenseFallback(
@@ -59,7 +62,8 @@ const ContractTab = withSuspenseFallback(
)
);
const TopicSchemaFields = withSuspenseFallback(
- lazy(() => import('../components/Topic/TopicSchema/TopicSchema'))
+ lazy(() => import('../components/Topic/TopicSchema/TopicSchema')),
+ TAB_CONTENT_FALLBACK
);
export const getTopicDetailsPageTabs = ({
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/WorksheetDetailsUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/WorksheetDetailsUtils.tsx
index 12f35efb7f37..fb3b121c65ef 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/WorksheetDetailsUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/WorksheetDetailsUtils.tsx
@@ -13,7 +13,9 @@
import { get } from 'lodash';
import { lazy } from 'react';
-import withSuspenseFallback from '../components/AppRouter/withSuspenseFallback';
+import withSuspenseFallback, {
+ TAB_CONTENT_FALLBACK,
+} from '../components/AppRouter/withSuspenseFallback';
import TabsLabel from '../components/common/TabsLabel/TabsLabel.component';
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
@@ -35,7 +37,8 @@ const WorksheetColumnsTable = withSuspenseFallback(
import(
'../components/DriveService/Worksheet/WorksheetColumnsTable/WorksheetColumnsTable'
)
- )
+ ),
+ TAB_CONTENT_FALLBACK
);
export interface WorksheetDetailPageTabProps {