From 064d91b7eb37d88c5f7842b06bc5ee053398856f Mon Sep 17 00:00:00 2001 From: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Date: Tue, 13 May 2025 17:05:51 +0530 Subject: [PATCH] feat(ui): store user preferences to localStorage (#21128) * feat(ui): store user preferences to localStorage * fix domain spec * fix sidebar causing unwanted failures * fix playwright adjust expandable cards * fix empty condition for cards * update condition (cherry picked from commit 3490a06ca2569bbf01f8c65948a21b7a0e59c0c8) --- .../ui/playwright/e2e/Pages/Domains.spec.ts | 8 ++ .../resources/ui/playwright/utils/domain.ts | 8 +- .../ui/playwright/utils/initialSetup.ts | 4 + .../components/AppContainer/AppContainer.tsx | 10 +- .../DomainLabelV2/DomainLabelV2.tsx | 3 +- .../DataAssets/OwnerLabelV2/OwnerLabelV2.tsx | 4 +- .../ReviewerLabelV2/ReviewerLabelV2.tsx | 3 +- .../DomainExpertWidget.tsx | 7 +- .../tabs/GlossaryTermReferences.tsx | 3 +- .../tabs/GlossaryTermSynonyms.tsx | 3 +- .../GlossaryTerms/tabs/RelatedTerms.tsx | 3 +- .../Metric/RelatedMetrics/RelatedMetrics.tsx | 3 +- .../LeftSidebar/LeftSidebar.component.tsx | 11 +-- .../MyData/LeftSidebar/LeftSidebar.test.tsx | 2 +- .../ui/src/components/NavBar/NavBar.tsx | 17 ++-- .../Tag/TagsContainerV2/TagsContainerV2.tsx | 3 +- .../ResizablePanels/resizable-panels.less | 2 +- .../currentUserStore/useCurrentUserStore.ts | 99 +++++++++++++++++++ .../FrequentlyJoinedTables.component.tsx | 3 +- .../PartitionedKeys.component.tsx | 3 +- .../TableConstraints/TableConstraints.tsx | 3 +- .../ui/src/styles/components/card.less | 7 +- 22 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/currentUserStore/useCurrentUserStore.ts diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts index 7b55e8ca182..52ffbc4d391 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts @@ -513,6 +513,10 @@ test.describe('Domains', () => { await domain.create(apiContext); await page.reload(); await sidebarClick(page, SidebarItem.DOMAIN); + await page.waitForLoadState('networkidle'); + await page.waitForSelector(`[data-testid="loader"]`, { + state: 'hidden', + }); await selectDomain(page, domain.data); await addTagsAndGlossaryToDomain(page, { @@ -522,6 +526,10 @@ test.describe('Domains', () => { await redirectToHomePage(page); await sidebarClick(page, SidebarItem.DOMAIN); + await page.waitForLoadState('networkidle'); + await page.waitForSelector(`[data-testid="loader"]`, { + state: 'hidden', + }); await selectDomain(page, domain.data); await page.waitForLoadState('networkidle'); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/domain.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/domain.ts index fc71d0b2436..a0028bf91e5 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/domain.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/domain.ts @@ -625,7 +625,13 @@ export const addTagsAndGlossaryToDomain = async ( const input = page.locator(`${container} #tagsForm_tags`); await input.click(); await input.fill(value); - await page.getByTestId(`tag-${value}`).click(); + const tag = page.getByTestId(`tag-${value}`); + if (containerType === 'glossary') { + // To avoid clicking on white space between checkbox and text + await tag.locator('.ant-select-tree-checkbox').click(); + } else { + await tag.click(); + } // Save and wait for response const updateResponse = page.waitForResponse( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/initialSetup.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/initialSetup.ts index 3ce83ab22da..30796429cc5 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/initialSetup.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/initialSetup.ts @@ -45,5 +45,9 @@ export const loginAsAdmin = async (page: Page, admin: AdminClass) => { await admin.logout(page); await page.waitForURL('**/signin'); await admin.login(page); + + // Close the leftside bar to run tests smoothly + await page.getByTestId('sidebar-toggle').click(); + await page.waitForURL('**/my-data'); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx index 02e0d68bab4..32d44444758 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx @@ -13,7 +13,7 @@ */ import { Layout } from 'antd'; import classNames from 'classnames'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { useLimitStore } from '../../context/LimitsProvider/useLimitsStore'; import { LineageSettings } from '../../generated/configuration/lineageSettings'; import { SettingType } from '../../generated/settings/settings'; @@ -36,7 +36,6 @@ const AppContainer = () => { const AuthenticatedRouter = applicationRoutesClass.getRouteElements(); const ApplicationExtras = applicationsClassBase.getApplicationExtension(); const { isAuthenticated } = useApplicationStore(); - const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(true); const { setConfig, bannerDetails } = useLimitStore(); @@ -71,16 +70,13 @@ const AppContainer = () => { ['extra-banner']: Boolean(bannerDetails), })}> {/* Render left side navigation */} - + {/* Render main content */} {/* Render Appbar */} {isProtectedRoute(location.pathname) && isAuthenticated ? ( - setIsSidebarCollapsed(!isSidebarCollapsed)} - /> + ) : null} {/* Render main content */} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DomainLabelV2/DomainLabelV2.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DomainLabelV2/DomainLabelV2.tsx index 43054a91e78..81b1410e7cd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DomainLabelV2/DomainLabelV2.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DomainLabelV2/DomainLabelV2.tsx @@ -182,7 +182,8 @@ export const DomainLabelV2 = < {selectableList} ), - }}> + }} + isExpandDisabled={!Array.isArray(domainLink)}>
{domainLink}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/OwnerLabelV2/OwnerLabelV2.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/OwnerLabelV2/OwnerLabelV2.tsx index 98bbad9c168..67b6cbce27e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/OwnerLabelV2/OwnerLabelV2.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/OwnerLabelV2/OwnerLabelV2.tsx @@ -12,6 +12,7 @@ */ import { Typography } from 'antd'; import { t } from 'i18next'; +import { isEmpty } from 'lodash'; import React, { useMemo } from 'react'; import { ReactComponent as PlusIcon } from '../../../assets/svg/plus-primary.svg'; import { TabSpecificField } from '../../../enums/entity.enum'; @@ -76,7 +77,8 @@ export const OwnerLabelV2 = < cardProps={{ title: header, }} - dataTestId={dataTestId}> + dataTestId={dataTestId} + isExpandDisabled={isEmpty(data.owners)}> {getOwnerVersionLabel( data, isVersionView ?? false, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/ReviewerLabelV2/ReviewerLabelV2.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/ReviewerLabelV2/ReviewerLabelV2.tsx index 24002d59e28..8c2c12072c4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/ReviewerLabelV2/ReviewerLabelV2.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/ReviewerLabelV2/ReviewerLabelV2.tsx @@ -100,7 +100,8 @@ export const ReviewerLabelV2 = < cardProps={{ title: header, }} - dataTestId="glossary-reviewer"> + dataTestId="glossary-reviewer" + isExpandDisabled={!hasReviewers}>
{getOwnerVersionLabel( data, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainExpertsWidget/DomainExpertWidget.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainExpertsWidget/DomainExpertWidget.tsx index 9cf794f3bc9..dc6984f2fe5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainExpertsWidget/DomainExpertWidget.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainExpertsWidget/DomainExpertWidget.tsx @@ -13,7 +13,7 @@ import { Typography } from 'antd'; import classNames from 'classnames'; import { t } from 'i18next'; -import { cloneDeep, includes, isEqual } from 'lodash'; +import { cloneDeep, includes, isEmpty, isEqual } from 'lodash'; import { default as React, useMemo } from 'react'; import { ReactComponent as PlusIcon } from '../../../assets/svg/plus-primary.svg'; import { TabSpecificField } from '../../../enums/entity.enum'; @@ -100,7 +100,7 @@ export const DomainExpertWidget = () => {
- {editOwnerPermission && domain.experts && domain.experts.length === 0 && ( + {editOwnerPermission && domain.experts?.length === 0 && ( { cardProps={{ title: header, }} - dataTestId="domain-expert-name"> + dataTestId="domain-expert-name" + isExpandDisabled={isEmpty(domain.experts)}> {content} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx index 1a2739bcf28..e3698f7796e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx @@ -147,7 +147,8 @@ const GlossaryTermReferences = () => { cardProps={{ title: header, }} - dataTestId="references-container"> + dataTestId="references-container" + isExpandDisabled={isEmpty(references)}> {isVersionView ? ( getVersionReferenceElements() ) : ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx index 0ed38256ba1..85917efa6cf 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx @@ -193,7 +193,8 @@ const GlossaryTermSynonyms = () => { cardProps={{ title: header, }} - dataTestId="synonyms-container"> + dataTestId="synonyms-container" + isExpandDisabled={isEmpty(synonyms)}> {isViewMode ? ( getSynonymsContainer() ) : ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx index 759236787d4..d10704b5ab2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx @@ -250,7 +250,8 @@ const RelatedTerms = () => { cardProps={{ title: header, }} - dataTestId="related-term-container"> + dataTestId="related-term-container" + isExpandDisabled={selectedOption.length === 0}> {isIconVisible ? ( relatedTermsContainer ) : ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/RelatedMetrics.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/RelatedMetrics.tsx index fadca4a0259..92f632337c6 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/RelatedMetrics.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/RelatedMetrics.tsx @@ -219,7 +219,8 @@ const RelatedMetrics: FC = ({ + }} + isExpandDisabled={isEmpty(relatedMetrics)}> {content} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx index c762d97e8ac..da1463dfb0b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx @@ -24,6 +24,7 @@ import { SIDEBAR_NESTED_KEYS, } from '../../../constants/LeftSidebar.constants'; import { SidebarItem } from '../../../enums/sidebar.enum'; +import { useCurrentUserPreferences } from '../../../hooks/currentUserStore/useCurrentUserStore'; import { useApplicationStore } from '../../../hooks/useApplicationStore'; import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation'; import { useCustomPages } from '../../../hooks/useCustomPages'; @@ -32,18 +33,16 @@ import BrandImage from '../../common/BrandImage/BrandImage'; import './left-sidebar.less'; import { LeftSidebarItem as LeftSidebarItemType } from './LeftSidebar.interface'; import LeftSidebarItem from './LeftSidebarItem.component'; - const { Sider } = Layout; -const LeftSidebar = ({ - isSidebarCollapsed, -}: { - isSidebarCollapsed: boolean; -}) => { +const LeftSidebar = () => { const location = useCustomLocation(); const { t } = useTranslation(); const { onLogoutHandler } = useApplicationStore(); const [showConfirmLogoutModal, setShowConfirmLogoutModal] = useState(false); + const { + preferences: { isSidebarCollapsed }, + } = useCurrentUserPreferences(); const { i18n } = useTranslation(); const isDirectionRTL = useMemo(() => i18n.dir() === 'rtl', [i18n]); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.test.tsx index eb2a4e045e2..eec546a700c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.test.tsx @@ -19,7 +19,7 @@ describe('LeftSidebar', () => { it('renders sidebar links correctly', () => { render( - + ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx b/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx index 058286d6340..40abdaeb4d3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx @@ -57,6 +57,7 @@ import { useWebSocketConnector } from '../../context/WebSocketProvider/WebSocket import { EntityTabs, EntityType } from '../../enums/entity.enum'; import { EntityReference } from '../../generated/entity/type'; import { BackgroundJob, JobType } from '../../generated/jobs/backgroundJob'; +import { useCurrentUserPreferences } from '../../hooks/currentUserStore/useCurrentUserStore'; import useCustomLocation from '../../hooks/useCustomLocation/useCustomLocation'; import { useDomainStore } from '../../hooks/useDomainStore'; import { getVersion } from '../../rest/miscAPI'; @@ -96,13 +97,7 @@ import popupAlertsCardsClassBase from './PopupAlertClassBase'; const cookieStorage = new CookieStorage(); -const NavBar = ({ - isSidebarCollapsed = true, - toggleSideBar, -}: { - isSidebarCollapsed?: boolean; - toggleSideBar?: () => void; -}) => { +const NavBar = () => { const { isTourOpen: isTourRoute } = useTourProvider(); const { onUpdateCSVExportJob } = useEntityExportModalProvider(); const { handleDeleteEntityWebsocketResponse } = useAsyncDeleteProvider(); @@ -123,6 +118,10 @@ const NavBar = ({ const [isFeatureModalOpen, setIsFeatureModalOpen] = useState(false); const [version, setVersion] = useState(); const [isDomainDropdownOpen, setIsDomainDropdownOpen] = useState(false); + const { + preferences: { isSidebarCollapsed }, + setPreference, + } = useCurrentUserPreferences(); const fetchOMVersion = async () => { try { @@ -423,7 +422,9 @@ const NavBar = ({ } size="middle" type="text" - onClick={toggleSideBar} + onClick={() => + setPreference({ isSidebarCollapsed: !isSidebarCollapsed }) + } /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx index f21e8da739e..38f40a9bba1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx @@ -427,7 +427,8 @@ const TagsContainerV2 = ({ cardProps={{ title: header, }} - dataTestId={isGlossaryType ? 'glossary-container' : 'tags-container'}> + dataTestId={isGlossaryType ? 'glossary-container' : 'tags-container'} + isExpandDisabled={isEmpty(tags?.[tagType])}> {suggestionDataRender ?? ( <> {tagBody} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/resizable-panels.less b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/resizable-panels.less index 3b3153cd173..59d3f04f04a 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/resizable-panels.less +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/resizable-panels.less @@ -273,7 +273,7 @@ h2.rotated-header { display: flex; flex-direction: column; - .ant-card-head { + & > .ant-card-head { padding: 0px 16px; border-bottom: none; } diff --git a/openmetadata-ui/src/main/resources/ui/src/hooks/currentUserStore/useCurrentUserStore.ts b/openmetadata-ui/src/main/resources/ui/src/hooks/currentUserStore/useCurrentUserStore.ts new file mode 100644 index 00000000000..4ed411d30e1 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/hooks/currentUserStore/useCurrentUserStore.ts @@ -0,0 +1,99 @@ +/* + * Copyright 2024 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 { create } from 'zustand'; +import { createJSONStorage, persist } from 'zustand/middleware'; +import { useApplicationStore } from '../useApplicationStore'; + +interface UserPreferences { + isSidebarCollapsed: boolean; +} + +interface Store { + preferences: Record; + setUserPreference: ( + userName: string, + preferences: Partial + ) => void; + getUserPreference: (userName: string) => UserPreferences; + clearUserPreference: (userName: string) => void; +} + +const defaultPreferences: UserPreferences = { + isSidebarCollapsed: false, + // Add default values for other preferences +}; + +export const usePersistentStorage = create()( + persist( + (set, get) => ({ + preferences: {}, + + setUserPreference: ( + userName: string, + newPreferences: Partial + ) => { + set((state) => ({ + preferences: { + ...state.preferences, + [userName]: { + ...defaultPreferences, + ...state.preferences[userName], + ...newPreferences, + }, + }, + })); + }, + + getUserPreference: (userName: string) => { + const state = get(); + + return state.preferences[userName] || defaultPreferences; + }, + + clearUserPreference: (userName: string) => { + set((state) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { [userName]: _, ...rest } = state.preferences; + + return { preferences: rest }; + }); + }, + }), + { + name: 'user-preferences-store', + storage: createJSONStorage(() => localStorage), + } + ) +); + +// Hook to easily access current user's preferences +export const useCurrentUserPreferences = () => { + const currentUser = useApplicationStore((state) => state.currentUser); + const { preferences, setUserPreference } = usePersistentStorage(); + + if (!currentUser?.name) { + return { + preferences: defaultPreferences, + setPreference: () => { + // update the user name in the local storage + }, + }; + } + + return { + preferences: preferences[currentUser.name] || defaultPreferences, + setPreference: (newPreferences: Partial) => + setUserPreference(currentUser.name, newPreferences), + }; +}; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/FrequentlyJoinedTables/FrequentlyJoinedTables.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/FrequentlyJoinedTables/FrequentlyJoinedTables.component.tsx index 2112f4ebbc1..56e4fce6194 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/FrequentlyJoinedTables/FrequentlyJoinedTables.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/FrequentlyJoinedTables/FrequentlyJoinedTables.component.tsx @@ -69,7 +69,8 @@ export const FrequentlyJoinedTables = () => { cardProps={{ title: t('label.frequently-joined-table-plural'), }} - dataTestId="frequently-joint-data-container"> + dataTestId="frequently-joint-data-container" + isExpandDisabled={isEmpty(joinedTables)}> {content} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/PartitionedKeys/PartitionedKeys.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/PartitionedKeys/PartitionedKeys.component.tsx index 15639893841..bfeab5cf660 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/PartitionedKeys/PartitionedKeys.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/PartitionedKeys/PartitionedKeys.component.tsx @@ -84,7 +84,8 @@ export const PartitionedKeys = () => { + }} + isExpandDisabled={isEmpty(partitionColumnDetails)}> {content} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableConstraints/TableConstraints.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableConstraints/TableConstraints.tsx index c5289a581a3..78490033c78 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableConstraints/TableConstraints.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableConstraints/TableConstraints.tsx @@ -178,7 +178,8 @@ const TableConstraints = () => { + }} + isExpandDisabled={isEmpty(data?.tableConstraints)}> {content} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/styles/components/card.less b/openmetadata-ui/src/main/resources/ui/src/styles/components/card.less index 38cb594fcf3..ffbdd015598 100644 --- a/openmetadata-ui/src/main/resources/ui/src/styles/components/card.less +++ b/openmetadata-ui/src/main/resources/ui/src/styles/components/card.less @@ -77,7 +77,6 @@ .ant-card.new-header-border-card { height: auto !important; - transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); .ant-card-head { background: @grey-50; border-radius: @border-radius-sm; @@ -89,6 +88,8 @@ .ant-card-body { height: auto !important; max-height: none !important; + transition: all 200ms ease; + transition-property: height, left, top; } .expand-collapse-icon { @@ -120,5 +121,9 @@ } } + .ant-card-extra { + margin-left: @size-sm; + } + border: 1px solid @grey-15; }