Skip to content

Commit 3129a14

Browse files
siddhant1Siddhantclaude
authored
refactor(ui): render Data Marketplace home page on the main app layout (#27377)
* refactor(ui): render Data Marketplace home page on the main app layout - Route /data-marketplace through the default AppContainer (LeftSidebar + NavBar). NavBar already styles itself transparent for this path, so the existing marketplace hero flows under it with no extra CSS. - Drop /data-marketplace/* sub-routes. MarketplaceLayout, MarketplaceNavBar, MarketplaceSubPageLayout, and the new core-components Sidebar remain on disk so the standalone shell can be reintroduced later. - Render home-page domain and data-product cards with Avatar + getEntityAvatarProps (same helper used by the old list and detail pages). Per-entity style.iconURL / style.color and the Globe01 / Cube01 fallbacks now match the rest of the app. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * lint * breadcrumb * fix * fix * test(playwright): skip marketplace specs tied to removed sub-routes The /data-marketplace/* sub-routes are removed in this refactor, so the five specs that assert those URLs no longer apply. Skip them until the standalone marketplace shell (and its routes) return. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style(playwright): apply prettier formatting to skipped marketplace test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Siddhant <siddhant@MacBook-Pro-621.local> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f69d753 commit 3129a14

11 files changed

Lines changed: 77 additions & 105 deletions

File tree

openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/DataMarketplace.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ test.describe(
128128
});
129129
});
130130

131-
test('Search returns results and clicking navigates to entity', async ({
131+
// Skipped: /data-marketplace/* sub-routes removed in PR #27377; re-enable when the standalone marketplace shell is reintroduced.
132+
test.skip('Search returns results and clicking navigates to entity', async ({
132133
page,
133134
}) => {
134135
test.slow();
@@ -170,7 +171,7 @@ test.describe(
170171
});
171172
});
172173

173-
test('Widget card click navigates to entity detail page', async ({
174+
test.skip('Widget card click navigates to entity detail page', async ({
174175
page,
175176
}) => {
176177
test.slow();
@@ -201,7 +202,7 @@ test.describe(
201202
});
202203
});
203204

204-
test('View All links navigate correctly', async ({ page }) => {
205+
test.skip('View All links navigate correctly', async ({ page }) => {
205206
test.slow();
206207

207208
await test.step('Navigate to marketplace', async () => {

openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/DataMarketplaceAnnouncements.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ test.describe(
9090
});
9191
});
9292

93-
test('Clicking announcement navigates to entity page', async ({ page }) => {
93+
test.skip('Clicking announcement navigates to entity page', async ({
94+
page,
95+
}) => {
9496
test.slow();
9597

9698
await test.step('Navigate to marketplace', async () => {

openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/DataMarketplacePermissions.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ test.describe(
130130
});
131131
});
132132

133-
test('Data consumer can search and view results', async ({
133+
test.skip('Data consumer can search and view results', async ({
134134
consumerPage,
135135
}) => {
136136
test.slow();

openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ import ForbiddenPage from '../../pages/ForbiddenPage/ForbiddenPage';
2828
import PlatformLineage from '../../pages/PlatformLineage/PlatformLineage';
2929
import TagPage from '../../pages/TagPage/TagPage';
3030
import { checkPermission, userPermissions } from '../../utils/PermissionsUtils';
31-
import { DataProductListPage as PureDataProductListPage } from '../DataProduct/DataProductListPage';
32-
import { DomainListPage as PureDomainListPage } from '../DomainListing/DomainListPage';
3331
import { useApplicationsProvider } from '../Settings/Applications/ApplicationsProvider/ApplicationsProvider';
3432
import { RoutePosition } from '../Settings/Applications/plugins/AppPlugin';
3533
import AdminProtectedRoute from './AdminProtectedRoute';
@@ -121,24 +119,6 @@ const DataMarketplacePage = withSuspenseFallback(
121119
)
122120
);
123121

124-
const MarketplaceLayout = withSuspenseFallback(
125-
React.lazy(
126-
() =>
127-
import(
128-
/* webpackChunkName: "MarketplaceLayout" */ '../../pages/DataMarketplacePage/MarketplaceLayout.component'
129-
)
130-
)
131-
);
132-
133-
const MarketplaceSubPageLayout = withSuspenseFallback(
134-
React.lazy(
135-
() =>
136-
import(
137-
/* webpackChunkName: "MarketplaceSubPageLayout" */ '../../pages/DataMarketplacePage/MarketplaceSubPageLayout.component'
138-
)
139-
)
140-
);
141-
142122
const BotDetailsPage = withSuspenseFallback(
143123
React.lazy(() => import('../../pages/BotDetailsPage/BotDetailsPage'))
144124
);
@@ -156,24 +136,6 @@ const UserPage = withSuspenseFallback(
156136
React.lazy(() => import('../../pages/UserPage/UserPage.component'))
157137
);
158138

159-
const DomainDetailPage = withSuspenseFallback(
160-
React.lazy(
161-
() =>
162-
import(
163-
/* webpackChunkName: "DomainDetailPage" */ '../../components/Domain/DomainDetailPage/DomainDetailPage.component'
164-
)
165-
)
166-
);
167-
168-
const DataProductsPage = withSuspenseFallback(
169-
React.lazy(
170-
() =>
171-
import(
172-
/* webpackChunkName: "DataProductsPage" */ '../../components/DataProducts/DataProductsPage/DataProductsPage.component'
173-
)
174-
)
175-
);
176-
177139
const DomainVersionPage = withSuspenseFallback(
178140
React.lazy(
179141
() =>
@@ -492,28 +454,7 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
492454
}
493455
path={ROUTES.MARKETPLACE_APP_INSTALL}
494456
/>
495-
<Route element={<MarketplaceLayout />} path={ROUTES.DATA_MARKETPLACE}>
496-
<Route index element={<DataMarketplacePage />} />
497-
<Route element={<MarketplaceSubPageLayout />}>
498-
<Route element={<PureDataProductListPage />} path="data-products" />
499-
<Route element={<PureDomainListPage />} path="domains" />
500-
<Route element={<DomainDetailPage />} path="domains/:fqn" />
501-
<Route element={<DomainDetailPage />} path="domains/:fqn/:tab" />
502-
<Route
503-
element={<DomainDetailPage />}
504-
path="domains/:fqn/:tab/:subTab"
505-
/>
506-
<Route element={<DataProductsPage />} path="data-products/:fqn" />
507-
<Route
508-
element={<DataProductsPage />}
509-
path="data-products/:fqn/:tab"
510-
/>
511-
<Route
512-
element={<DataProductsPage />}
513-
path="data-products/:fqn/:tab/:subTab"
514-
/>
515-
</Route>
516-
</Route>
457+
<Route element={<DataMarketplacePage />} path={ROUTES.DATA_MARKETPLACE} />
517458
<Route element={<SwaggerPage />} path={ROUTES.SWAGGER} />
518459
<Route element={<DomainVersionPage />} path={ROUTES.DOMAIN_VERSION} />
519460
<Route element={<UserPage />} path={ROUTES.USER_PROFILE_WITH_SUB_TAB} />

openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceDataProductsWidget/MarketplaceDataProductsWidget.component.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* limitations under the License.
1212
*/
1313

14-
import { Button, Typography } from '@openmetadata/ui-core-components';
14+
import { Avatar, Button, Typography } from '@openmetadata/ui-core-components';
1515
import { useForm } from 'antd/lib/form/Form';
1616
import { isEmpty, noop } from 'lodash';
1717
import { useSnackbar } from 'notistack';
@@ -35,7 +35,7 @@ import { searchData } from '../../../rest/miscAPI';
3535
import { getTextFromHtmlString } from '../../../utils/BlockEditorUtils';
3636
import { createEntityWithCoverImage } from '../../../utils/CoverImageUploadUtils';
3737
import dataMarketplaceClassBase from '../../../utils/DataMarketplace/DataMarketplaceClassBase';
38-
import { getDataProductIconByUrl } from '../../../utils/DataProductUtils';
38+
import { getEntityAvatarProps } from '../../../utils/IconUtils';
3939
import { getEncodedFqn } from '../../../utils/StringsUtils';
4040
import { useFormDrawerWithRef } from '../../common/atoms/drawer';
4141
import Loader from '../../common/Loader/Loader';
@@ -148,7 +148,8 @@ const MarketplaceDataProductsWidget = ({
148148
return;
149149
}
150150
navigate(
151-
`${dataProductBasePath}/${getEncodedFqn(dp.fullyQualifiedName ?? '')}`
151+
`${dataProductBasePath}/${getEncodedFqn(dp.fullyQualifiedName ?? '')}`,
152+
{ state: { fromMarketplace: true } }
152153
);
153154
},
154155
[navigate, isEditView, dataProductBasePath]
@@ -159,9 +160,16 @@ const MarketplaceDataProductsWidget = ({
159160
<div className="marketplace-widget-cards">
160161
{dataProducts.map((dp) => (
161162
<MarketplaceItemCard
162-
backgroundColor={dp.style?.color}
163163
dataTestId={`marketplace-dp-card-${dp.id}`}
164-
icon={getDataProductIconByUrl(dp.style?.iconURL)}
164+
icon={
165+
<Avatar
166+
size="md"
167+
{...getEntityAvatarProps({
168+
...dp,
169+
entityType: 'dataProduct',
170+
})}
171+
/>
172+
}
165173
key={dp.id}
166174
name={dp.displayName || dp.name}
167175
subtitle={getTextFromHtmlString(dp.description)}

openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceDomainsWidget/MarketplaceDomainsWidget.component.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* limitations under the License.
1212
*/
1313

14-
import { Button, Typography } from '@openmetadata/ui-core-components';
14+
import { Avatar, Button, Typography } from '@openmetadata/ui-core-components';
1515
import { useForm } from 'antd/lib/form/Form';
1616
import { isEmpty, noop } from 'lodash';
1717
import { useSnackbar } from 'notistack';
@@ -31,7 +31,7 @@ import { addDomains, patchDomains } from '../../../rest/domainAPI';
3131
import { searchQuery } from '../../../rest/searchAPI';
3232
import { createEntityWithCoverImage } from '../../../utils/CoverImageUploadUtils';
3333
import dataMarketplaceClassBase from '../../../utils/DataMarketplace/DataMarketplaceClassBase';
34-
import { getDomainIcon } from '../../../utils/DomainUtils';
34+
import { getEntityAvatarProps } from '../../../utils/IconUtils';
3535
import { getDomainDetailsPath } from '../../../utils/RouterUtils';
3636
import { useFormDrawerWithRef } from '../../common/atoms/drawer';
3737
import Loader from '../../common/Loader/Loader';
@@ -140,7 +140,9 @@ const MarketplaceDomainsWidget = ({
140140
if (isEditView) {
141141
return;
142142
}
143-
navigate(getDomainDetailsPath(domain.fullyQualifiedName ?? ''));
143+
navigate(getDomainDetailsPath(domain.fullyQualifiedName ?? ''), {
144+
state: { fromMarketplace: true },
145+
});
144146
},
145147
[navigate, isEditView]
146148
);
@@ -150,9 +152,13 @@ const MarketplaceDomainsWidget = ({
150152
<div className="marketplace-widget-cards">
151153
{domains.map((domain) => (
152154
<MarketplaceItemCard
153-
backgroundColor={domain.style?.color}
154155
dataTestId={`marketplace-domain-card-${domain.id}`}
155-
icon={getDomainIcon(domain.style?.iconURL)}
156+
icon={
157+
<Avatar
158+
size="md"
159+
{...getEntityAvatarProps({ ...domain, entityType: 'domain' })}
160+
/>
161+
}
156162
key={domain.id}
157163
name={domain.displayName || domain.name}
158164
subtitle={

openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceItemCard/MarketplaceItemCard.component.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ interface MarketplaceItemCardProps {
1818
icon: ReactNode;
1919
name: string;
2020
subtitle: string;
21-
backgroundColor?: string;
2221
onClick: () => void;
2322
dataTestId?: string;
2423
}
@@ -27,7 +26,6 @@ const MarketplaceItemCard = ({
2726
icon,
2827
name,
2928
subtitle,
30-
backgroundColor,
3129
onClick,
3230
dataTestId,
3331
}: MarketplaceItemCardProps) => {
@@ -45,13 +43,7 @@ const MarketplaceItemCard = ({
4543
onClick();
4644
}
4745
}}>
48-
<div
49-
className="tw:flex tw:items-center tw:justify-center tw:w-10 tw:h-10 tw:min-w-10 tw:rounded-lg tw:text-white"
50-
style={{ backgroundColor: backgroundColor ?? '#E0E7FF' }}>
51-
<span className="tw:w-6 tw:h-6 tw:flex tw:items-center tw:justify-center">
52-
{icon}
53-
</span>
54-
</div>
46+
{icon}
5547
<div className="tw:flex tw:flex-col tw:min-w-0 tw:gap-0.5">
5648
<Typography
5749
as="span"

openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.component.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ const MarketplaceSearchBar = ({ isEditView }: { isEditView?: boolean }) => {
126126
(dp: DataProduct) => {
127127
setIsOpen(false);
128128
navigate(
129-
`${dataProductBasePath}/${getEncodedFqn(dp.fullyQualifiedName ?? '')}`
129+
`${dataProductBasePath}/${getEncodedFqn(dp.fullyQualifiedName ?? '')}`,
130+
{ state: { fromMarketplace: true } }
130131
);
131132
},
132133
[navigate, dataProductBasePath]
@@ -135,7 +136,9 @@ const MarketplaceSearchBar = ({ isEditView }: { isEditView?: boolean }) => {
135136
const handleDomainClick = useCallback(
136137
(domain: Domain) => {
137138
setIsOpen(false);
138-
navigate(getDomainDetailsPath(domain.fullyQualifiedName ?? ''));
139+
navigate(getDomainDetailsPath(domain.fullyQualifiedName ?? ''), {
140+
state: { fromMarketplace: true },
141+
});
139142
},
140143
[navigate]
141144
);
@@ -248,7 +251,7 @@ const MarketplaceSearchBar = ({ isEditView }: { isEditView?: boolean }) => {
248251
<Input
249252
autoComplete="off"
250253
data-testid="marketplace-search-input"
251-
fontSize="xs"
254+
fontSize="sm"
252255
icon={SearchLg}
253256
iconClassName="tw:!size-4"
254257
inputClassName="tw:!pl-9"
@@ -258,7 +261,7 @@ const MarketplaceSearchBar = ({ isEditView }: { isEditView?: boolean }) => {
258261
t('label.data-product-plural') + ', ' + t('label.domain-plural'),
259262
})}
260263
value={searchValue}
261-
wrapperClassName="marketplace-search-input tw:!items-center"
264+
wrapperClassName="marketplace-search-input tw:!rounded-xl tw:!items-center tw:!py-1"
262265
onChange={(value) => handleChange(value)}
263266
onKeyDown={(e) => {
264267
if (e.key === 'Enter') {

openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { isEmpty, toLower, toString } from 'lodash';
2121
import { useSnackbar } from 'notistack';
2222
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2323
import { useTranslation } from 'react-i18next';
24-
import { useNavigate } from 'react-router-dom';
24+
import { useLocation, useNavigate } from 'react-router-dom';
2525
import { ReactComponent as IconAnnouncementsBlack } from '../../../assets/svg/announcements-black.svg';
2626
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
2727
import { ReactComponent as DeleteIcon } from '../../../assets/svg/ic-delete.svg';
@@ -136,6 +136,10 @@ const DataProductsDetailsPage = ({
136136
const { enqueueSnackbar } = useSnackbar();
137137
const navigate = useNavigate();
138138
const { isMarketplace, dataProductBasePath } = useMarketplaceStore();
139+
const location = useLocation();
140+
const fromMarketplace =
141+
(location.state as { fromMarketplace?: boolean } | null)?.fromMarketplace ??
142+
false;
139143
const { getEntityPermission } = usePermissionProvider();
140144
const { tab: activeTab, version } = useRequiredParams<{
141145
tab: string;
@@ -240,10 +244,17 @@ const DataProductsDetailsPage = ({
240244
});
241245
}
242246

243-
items.push({
244-
name: t('label.data-product-plural'),
245-
url: dataProductBasePath,
246-
});
247+
items.push(
248+
fromMarketplace
249+
? {
250+
name: t('label.data-marketplace'),
251+
url: ROUTES.DATA_MARKETPLACE,
252+
}
253+
: {
254+
name: t('label.data-product-plural'),
255+
url: dataProductBasePath,
256+
}
257+
);
247258

248259
if (dataProduct.domains && dataProduct.domains.length > 0) {
249260
items.push({
@@ -253,7 +264,13 @@ const DataProductsDetailsPage = ({
253264
}
254265

255266
return items;
256-
}, [dataProduct.domains, isMarketplace, dataProductBasePath, t]);
267+
}, [
268+
dataProduct.domains,
269+
isMarketplace,
270+
fromMarketplace,
271+
dataProductBasePath,
272+
t,
273+
]);
257274

258275
const { breadcrumbs } = useBreadcrumbs({ items: breadcrumbItems });
259276

0 commit comments

Comments
 (0)