mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-27 15:38:43 +00:00
chore(ui): refactored landing page layout (#13606)
This commit is contained in:
parent
599d0e96ad
commit
52c316e644
@ -50,7 +50,7 @@ import {
|
||||
} from '../../../utils/EntityUtils';
|
||||
import Loader from '../../Loader/Loader';
|
||||
import { TaskTab } from '../../Task/TaskTab/TaskTab.component';
|
||||
import '../../Widgets/FeedsWidget/feeds-widget.less';
|
||||
import '../../Widgets/FeedsWidget/FeedsWidget.less';
|
||||
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
||||
import ActivityFeedListV1 from '../ActivityFeedList/ActivityFeedListV1.component';
|
||||
import FeedPanelBodyV1 from '../ActivityFeedPanel/FeedPanelBodyV1';
|
||||
|
||||
@ -11,12 +11,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Button, Col, Modal, Row, Space, Typography } from 'antd';
|
||||
import { Button, Col, Modal, Space, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, isNil, uniqBy } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Layout, Responsive, WidthProvider } from 'react-grid-layout';
|
||||
import RGL, { Layout, WidthProvider } from 'react-grid-layout';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link, useHistory, useLocation, useParams } from 'react-router-dom';
|
||||
import AppState from '../../../AppState';
|
||||
@ -40,7 +39,9 @@ import { Transi18next } from '../../../utils/CommonUtils';
|
||||
import {
|
||||
getAddWidgetHandler,
|
||||
getLayoutUpdateHandler,
|
||||
getLayoutWithEmptyWidgetPlaceholder,
|
||||
getRemoveWidgetHandler,
|
||||
getWidgetFromKey,
|
||||
} from '../../../utils/CustomizableLandingPageUtils';
|
||||
import customizePageClassBase from '../../../utils/CustomizePageClassBase';
|
||||
import {
|
||||
@ -50,12 +51,11 @@ import {
|
||||
import { getDecodedFqn } from '../../../utils/StringsUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import ActivityFeedProvider from '../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||
import RightSidebar from '../../MyData/RightSidebar/RightSidebar.component';
|
||||
import PageLayoutV1 from '../../containers/PageLayoutV1';
|
||||
import AddWidgetModal from '../AddWidgetModal/AddWidgetModal';
|
||||
import EmptyWidgetPlaceholder from '../EmptyWidgetPlaceholder/EmptyWidgetPlaceholder';
|
||||
import { CustomizeMyDataProps } from './CustomizeMyData.interface';
|
||||
|
||||
const ResponsiveGridLayout = WidthProvider(Responsive);
|
||||
const ReactGridLayout = WidthProvider(RGL);
|
||||
|
||||
function CustomizeMyData({
|
||||
initialPageData,
|
||||
@ -67,20 +67,15 @@ function CustomizeMyData({
|
||||
const history = useHistory();
|
||||
const { fqn: personaFQN } = useParams<{ fqn: string; pageFqn: PageType }>();
|
||||
const location = useLocation();
|
||||
const [resetRightPanelLayout, setResetRightPanelLayout] =
|
||||
useState<boolean>(false);
|
||||
const [layout, setLayout] = useState<Array<WidgetConfig>>([
|
||||
...(initialPageData.data?.page?.layout ??
|
||||
customizePageClassBase.landingPageDefaultLayout),
|
||||
{
|
||||
h: 2,
|
||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||
w: 3,
|
||||
x: 0,
|
||||
y: 100,
|
||||
isDraggable: false,
|
||||
},
|
||||
]);
|
||||
const [layout, setLayout] = useState<Array<WidgetConfig>>(
|
||||
getLayoutWithEmptyWidgetPlaceholder(
|
||||
initialPageData.data?.page?.layout ??
|
||||
customizePageClassBase.defaultLayout,
|
||||
2,
|
||||
4
|
||||
)
|
||||
);
|
||||
|
||||
const [placeholderWidgetKey, setPlaceholderWidgetKey] = useState<string>(
|
||||
LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER
|
||||
);
|
||||
@ -108,19 +103,11 @@ function CustomizeMyData({
|
||||
setPlaceholderWidgetKey(value);
|
||||
}, []);
|
||||
|
||||
const handleResetRightPanelLayout = useCallback((value: boolean) => {
|
||||
setResetRightPanelLayout(value);
|
||||
}, []);
|
||||
|
||||
const handleLayoutChange = useCallback((newLayout: Array<WidgetConfig>) => {
|
||||
setLayout(newLayout);
|
||||
}, []);
|
||||
|
||||
const handleRemoveWidget = useCallback((widgetKey: string) => {
|
||||
setLayout(getRemoveWidgetHandler(widgetKey, 3, 3.5));
|
||||
}, []);
|
||||
|
||||
const handleAddWidget = useCallback(
|
||||
const handleMainPanelAddWidget = useCallback(
|
||||
(
|
||||
newWidgetData: Document,
|
||||
placeholderWidgetKey: string,
|
||||
@ -136,7 +123,7 @@ function CustomizeMyData({
|
||||
);
|
||||
setIsWidgetModalOpen(false);
|
||||
},
|
||||
[layout]
|
||||
[]
|
||||
);
|
||||
|
||||
const handleLayoutUpdate = useCallback(
|
||||
@ -189,71 +176,6 @@ function CustomizeMyData({
|
||||
}
|
||||
};
|
||||
|
||||
const getWidgetFromKey = useCallback(
|
||||
(widgetConfig: WidgetConfig) => {
|
||||
if (widgetConfig.i.endsWith('.EmptyWidgetPlaceholder')) {
|
||||
return (
|
||||
<EmptyWidgetPlaceholder
|
||||
handleOpenAddWidgetModal={handleOpenAddWidgetModal}
|
||||
handlePlaceholderWidgetKey={handlePlaceholderWidgetKey}
|
||||
handleRemoveWidget={handleRemoveWidget}
|
||||
isEditable={widgetConfig.isDraggable}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (widgetConfig.i.startsWith(LandingPageWidgetKeys.RIGHT_PANEL)) {
|
||||
return (
|
||||
<div className="h-full border-left p-l-md">
|
||||
<RightSidebar
|
||||
isEditView
|
||||
announcements={announcements}
|
||||
followedData={followedData ?? []}
|
||||
followedDataCount={followedDataCount}
|
||||
handleResetLayout={handleResetRightPanelLayout}
|
||||
handleSaveCurrentPageLayout={handleSaveCurrentPageLayout}
|
||||
isAnnouncementLoading={isAnnouncementLoading}
|
||||
isLoadingOwnedData={isLoadingOwnedData}
|
||||
layoutConfigData={widgetConfig.data}
|
||||
parentLayoutData={layout}
|
||||
resetLayout={resetRightPanelLayout}
|
||||
updateParentLayout={handleLayoutChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||
|
||||
return (
|
||||
<Widget
|
||||
isEditView
|
||||
announcements={announcements}
|
||||
followedData={followedData ?? []}
|
||||
followedDataCount={followedDataCount}
|
||||
handleRemoveWidget={handleRemoveWidget}
|
||||
isLoadingOwnedData={isLoadingOwnedData}
|
||||
selectedGridSize={widgetConfig.w}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[
|
||||
handleOpenAddWidgetModal,
|
||||
handleRemoveWidget,
|
||||
followedData,
|
||||
followedDataCount,
|
||||
isLoadingOwnedData,
|
||||
layout,
|
||||
handleLayoutChange,
|
||||
isAnnouncementLoading,
|
||||
announcements,
|
||||
resetRightPanelLayout,
|
||||
handleResetRightPanelLayout,
|
||||
handlePlaceholderWidgetKey,
|
||||
]
|
||||
);
|
||||
|
||||
const addedWidgetsList = useMemo(
|
||||
() =>
|
||||
layout
|
||||
@ -265,16 +187,32 @@ function CustomizeMyData({
|
||||
const widgets = useMemo(
|
||||
() =>
|
||||
layout.map((widget) => (
|
||||
<div
|
||||
className={classNames({
|
||||
'mt--1': widget.i === LandingPageWidgetKeys.RIGHT_PANEL,
|
||||
<div data-grid={widget} id={widget.i} key={widget.i}>
|
||||
{getWidgetFromKey({
|
||||
announcements: announcements,
|
||||
followedData: followedData ?? [],
|
||||
followedDataCount: followedDataCount,
|
||||
isLoadingOwnedData: isLoadingOwnedData,
|
||||
widgetConfig: widget,
|
||||
handleOpenAddWidgetModal: handleOpenAddWidgetModal,
|
||||
handlePlaceholderWidgetKey: handlePlaceholderWidgetKey,
|
||||
handleRemoveWidget: handleRemoveWidget,
|
||||
isEditView: true,
|
||||
isAnnouncementLoading: isAnnouncementLoading,
|
||||
})}
|
||||
data-grid={widget}
|
||||
key={widget.i}>
|
||||
{getWidgetFromKey(widget)}
|
||||
</div>
|
||||
)),
|
||||
[layout, getWidgetFromKey]
|
||||
[
|
||||
layout,
|
||||
announcements,
|
||||
followedData,
|
||||
followedDataCount,
|
||||
isLoadingOwnedData,
|
||||
handleOpenAddWidgetModal,
|
||||
handlePlaceholderWidgetKey,
|
||||
handleRemoveWidget,
|
||||
isAnnouncementLoading,
|
||||
]
|
||||
);
|
||||
|
||||
const fetchAnnouncements = useCallback(async () => {
|
||||
@ -299,10 +237,11 @@ function CustomizeMyData({
|
||||
...initialPageData,
|
||||
data: {
|
||||
page: {
|
||||
...initialPageData.data.page,
|
||||
layout: uniqBy(
|
||||
layout.filter(
|
||||
(widget) => !widget.i.endsWith('.EmptyWidgetPlaceholder')
|
||||
(widget) =>
|
||||
widget.i.startsWith('KnowledgePanel') &&
|
||||
!widget.i.endsWith('.EmptyWidgetPlaceholder')
|
||||
),
|
||||
'i'
|
||||
),
|
||||
@ -321,18 +260,17 @@ function CustomizeMyData({
|
||||
}, []);
|
||||
|
||||
const handleReset = useCallback(() => {
|
||||
setLayout([
|
||||
...customizePageClassBase.landingPageDefaultLayout,
|
||||
{
|
||||
h: 2,
|
||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||
w: 3,
|
||||
x: 0,
|
||||
y: 100,
|
||||
isDraggable: false,
|
||||
const newMainPanelLayout = customizePageClassBase.defaultLayout;
|
||||
setLayout(newMainPanelLayout);
|
||||
handlePageDataChange({
|
||||
...initialPageData,
|
||||
data: {
|
||||
page: {
|
||||
layout: uniqBy(newMainPanelLayout, 'i'),
|
||||
},
|
||||
},
|
||||
]);
|
||||
setResetRightPanelLayout(true);
|
||||
});
|
||||
handleSaveCurrentPageLayout(true);
|
||||
setIsResetModalOpen(false);
|
||||
}, []);
|
||||
|
||||
@ -347,83 +285,86 @@ function CustomizeMyData({
|
||||
}, [AppState.userDetails, AppState.users, isAuthDisabled]);
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col
|
||||
className="bg-white d-flex justify-between border-bottom p-sm"
|
||||
span={24}>
|
||||
<div className="d-flex gap-2 items-center">
|
||||
<Typography.Title className="m-0" level={5}>
|
||||
<Transi18next
|
||||
i18nKey="message.customize-landing-page-header"
|
||||
renderElement={
|
||||
<Link
|
||||
style={{ color: '#1890ff', fontSize: '16px' }}
|
||||
to={getPersonaDetailsPath(decodedPersonaFQN)}
|
||||
<ActivityFeedProvider>
|
||||
<PageLayoutV1
|
||||
header={
|
||||
<Col
|
||||
className="bg-white d-flex justify-between border-bottom p-sm"
|
||||
span={24}>
|
||||
<div className="d-flex gap-2 items-center">
|
||||
<Typography.Title className="m-0" level={5}>
|
||||
<Transi18next
|
||||
i18nKey="message.customize-landing-page-header"
|
||||
renderElement={
|
||||
<Link
|
||||
style={{ color: '#1890ff', fontSize: '16px' }}
|
||||
to={getPersonaDetailsPath(decodedPersonaFQN)}
|
||||
/>
|
||||
}
|
||||
values={{
|
||||
persona: decodedPersonaFQN,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
values={{
|
||||
persona: decodedPersonaFQN,
|
||||
}}
|
||||
/>
|
||||
</Typography.Title>
|
||||
</div>
|
||||
<Space>
|
||||
<Button size="small" onClick={handleCancel}>
|
||||
{t('label.cancel')}
|
||||
</Button>
|
||||
<Button size="small" onClick={handleOpenResetModal}>
|
||||
{t('label.reset')}
|
||||
</Button>
|
||||
<Button size="small" type="primary" onClick={onSaveLayout}>
|
||||
{t('label.save')}
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<ActivityFeedProvider>
|
||||
<ResponsiveGridLayout
|
||||
autoSize
|
||||
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
|
||||
className="grid-container"
|
||||
cols={{ lg: 4, md: 4, sm: 4, xs: 4, xxs: 4 }}
|
||||
draggableHandle=".drag-widget-icon"
|
||||
isResizable={false}
|
||||
margin={[
|
||||
customizePageClassBase.landingPageWidgetMargin,
|
||||
customizePageClassBase.landingPageWidgetMargin,
|
||||
]}
|
||||
rowHeight={customizePageClassBase.landingPageRowHeight}
|
||||
style={{
|
||||
backgroundImage: `url(${gridBgImg})`,
|
||||
}}
|
||||
onLayoutChange={handleLayoutUpdate}>
|
||||
{widgets}
|
||||
</ResponsiveGridLayout>
|
||||
{isWidgetModalOpen && (
|
||||
<AddWidgetModal
|
||||
addedWidgetsList={addedWidgetsList}
|
||||
handleAddWidget={handleAddWidget}
|
||||
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
||||
maxGridSizeSupport={customizePageClassBase.landingPageMaxGridSize}
|
||||
open={isWidgetModalOpen}
|
||||
placeholderWidgetKey={placeholderWidgetKey}
|
||||
/>
|
||||
)}
|
||||
{isResetModalOpen && (
|
||||
<Modal
|
||||
centered
|
||||
cancelText={t('label.no')}
|
||||
okText={t('label.yes')}
|
||||
open={isResetModalOpen}
|
||||
title={t('label.reset-default-layout')}
|
||||
onCancel={handleCloseResetModal}
|
||||
onOk={handleReset}>
|
||||
{t('message.reset-layout-confirmation')}
|
||||
</Modal>
|
||||
)}
|
||||
</ActivityFeedProvider>
|
||||
</Col>
|
||||
</Row>
|
||||
</Typography.Title>
|
||||
</div>
|
||||
<Space>
|
||||
<Button size="small" onClick={handleCancel}>
|
||||
{t('label.cancel')}
|
||||
</Button>
|
||||
<Button size="small" onClick={handleOpenResetModal}>
|
||||
{t('label.reset')}
|
||||
</Button>
|
||||
<Button size="small" type="primary" onClick={onSaveLayout}>
|
||||
{t('label.save')}
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
}
|
||||
headerClassName="m-0 p-0"
|
||||
mainContainerClassName="p-t-0"
|
||||
pageContainerStyle={{
|
||||
backgroundImage: `url(${gridBgImg})`,
|
||||
}}
|
||||
pageTitle={t('label.customize-entity', {
|
||||
entity: t('label.landing-page'),
|
||||
})}>
|
||||
<ReactGridLayout
|
||||
className="grid-container"
|
||||
cols={4}
|
||||
draggableHandle=".drag-widget-icon"
|
||||
isResizable={false}
|
||||
margin={[
|
||||
customizePageClassBase.landingPageWidgetMargin,
|
||||
customizePageClassBase.landingPageWidgetMargin,
|
||||
]}
|
||||
rowHeight={customizePageClassBase.landingPageRowHeight}
|
||||
onLayoutChange={handleLayoutUpdate}>
|
||||
{widgets}
|
||||
</ReactGridLayout>
|
||||
</PageLayoutV1>
|
||||
{isWidgetModalOpen && (
|
||||
<AddWidgetModal
|
||||
addedWidgetsList={addedWidgetsList}
|
||||
handleAddWidget={handleMainPanelAddWidget}
|
||||
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
||||
maxGridSizeSupport={customizePageClassBase.landingPageMaxGridSize}
|
||||
open={isWidgetModalOpen}
|
||||
placeholderWidgetKey={placeholderWidgetKey}
|
||||
/>
|
||||
)}
|
||||
{isResetModalOpen && (
|
||||
<Modal
|
||||
centered
|
||||
cancelText={t('label.no')}
|
||||
okText={t('label.yes')}
|
||||
open={isResetModalOpen}
|
||||
title={t('label.reset-default-layout')}
|
||||
onCancel={handleCloseResetModal}
|
||||
onOk={handleReset}>
|
||||
{t('message.reset-layout-confirmation')}
|
||||
</Modal>
|
||||
)}
|
||||
</ActivityFeedProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ const MyDataWidgetInternal = ({
|
||||
includeData.includes(data.type as AssetsType)
|
||||
);
|
||||
|
||||
setData(includedOwnsData.slice(0, 9));
|
||||
setData(includedOwnsData.slice(0, 8));
|
||||
setTotalOwnedAssetsCount(includedOwnsData.length);
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@ -10,8 +10,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
.announcement-container-list {
|
||||
.feed-card-body {
|
||||
padding: 0;
|
||||
.announcement-container {
|
||||
.ant-card-body {
|
||||
height: 100%;
|
||||
}
|
||||
.announcement-container-list {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 90%;
|
||||
.feed-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { CloseOutlined, DragOutlined } from '@ant-design/icons';
|
||||
import { Alert, Col, Row, Space, Typography } from 'antd';
|
||||
import { Alert, Card, Col, Row, Space, Typography } from 'antd';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -20,8 +20,11 @@ import { Thread } from '../../../generated/entity/feed/thread';
|
||||
import { WidgetCommonProps } from '../../../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import FeedCardBodyV1 from '../../ActivityFeed/ActivityFeedCard/FeedCardBody/FeedCardBodyV1';
|
||||
import FeedCardHeaderV1 from '../../ActivityFeed/ActivityFeedCard/FeedCardHeader/FeedCardHeaderV1';
|
||||
import Loader from '../../Loader/Loader';
|
||||
import './AnnouncementsWidget.less';
|
||||
|
||||
export interface AnnouncementsWidgetProps extends WidgetCommonProps {
|
||||
isAnnouncementLoading?: boolean;
|
||||
announcements: Thread[];
|
||||
}
|
||||
|
||||
@ -30,6 +33,7 @@ function AnnouncementsWidget({
|
||||
isEditView,
|
||||
handleRemoveWidget,
|
||||
widgetKey,
|
||||
isAnnouncementLoading = false,
|
||||
}: Readonly<AnnouncementsWidgetProps>) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -38,7 +42,7 @@ function AnnouncementsWidget({
|
||||
}, [widgetKey]);
|
||||
|
||||
return (
|
||||
<div className="bg-white h-full h-max-full overflow-y-scroll no-scrollbar">
|
||||
<Card className="announcement-container card-widget h-full">
|
||||
<Row justify="space-between">
|
||||
<Col>
|
||||
<Typography.Paragraph className="right-panel-label m-b-sm">
|
||||
@ -57,52 +61,59 @@ function AnnouncementsWidget({
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<div className="announcement-container-list">
|
||||
{isEmpty(announcements) && (
|
||||
<Typography.Text className="text-xs">
|
||||
{t('message.no-entity-data-available', {
|
||||
entity: t('label.announcement-lowercase'),
|
||||
{isAnnouncementLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<div className="announcement-container-list">
|
||||
{isEmpty(announcements) && (
|
||||
<Typography.Text className="text-xs">
|
||||
{t('message.no-entity-data-available', {
|
||||
entity: t('label.announcement-lowercase'),
|
||||
})}
|
||||
</Typography.Text>
|
||||
)}
|
||||
<Row gutter={[8, 8]}>
|
||||
{announcements.map((item) => {
|
||||
return (
|
||||
<Col key={item.id} span={24}>
|
||||
<Alert
|
||||
className="right-panel-announcement"
|
||||
description={
|
||||
<>
|
||||
<FeedCardHeaderV1
|
||||
about={item.about}
|
||||
className="d-inline"
|
||||
createdBy={item.createdBy}
|
||||
showUserAvatar={false}
|
||||
timeStamp={item.threadTs}
|
||||
/>
|
||||
<FeedCardBodyV1
|
||||
isOpenInDrawer
|
||||
announcement={item.announcement}
|
||||
className="p-t-xs"
|
||||
isEditPost={false}
|
||||
message={item.message}
|
||||
showSchedule={false}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
message={
|
||||
<div className="d-flex announcement-alert-heading">
|
||||
<AnnouncementIcon width={20} />
|
||||
<span className="text-sm p-l-xss">
|
||||
{t('label.announcement')}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
type="info"
|
||||
/>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Typography.Text>
|
||||
)}
|
||||
{announcements.map((item) => {
|
||||
return (
|
||||
<Alert
|
||||
className="m-b-xs right-panel-announcement"
|
||||
description={
|
||||
<>
|
||||
<FeedCardHeaderV1
|
||||
about={item.about}
|
||||
className="d-inline"
|
||||
createdBy={item.createdBy}
|
||||
showUserAvatar={false}
|
||||
timeStamp={item.threadTs}
|
||||
/>
|
||||
<FeedCardBodyV1
|
||||
isOpenInDrawer
|
||||
announcement={item.announcement}
|
||||
className="p-t-xs"
|
||||
isEditPost={false}
|
||||
message={item.message}
|
||||
showSchedule={false}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
key={item.id}
|
||||
message={
|
||||
<div className="d-flex announcement-alert-heading">
|
||||
<AnnouncementIcon width={20} />
|
||||
<span className="text-sm p-l-xss">
|
||||
{t('label.announcement')}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
type="info"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { CloseOutlined, DragOutlined } from '@ant-design/icons';
|
||||
import { Space } from 'antd';
|
||||
import { Card, Space } from 'antd';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -44,7 +44,7 @@ function FollowingWidget({
|
||||
}, [widgetKey]);
|
||||
|
||||
return (
|
||||
<div className="bg-white h-full" data-testid="following-data-container">
|
||||
<Card className="card-widget h-full" data-testid="following-data-container">
|
||||
<EntityListWithV1
|
||||
entityList={followedData}
|
||||
headerText={
|
||||
@ -78,7 +78,7 @@ function FollowingWidget({
|
||||
noDataPlaceholder={t('message.not-followed-anything')}
|
||||
testIDText="following"
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,262 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 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 { isEmpty, isUndefined, uniqBy } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Layout, Responsive, WidthProvider } from 'react-grid-layout';
|
||||
import { SIZE } from '../../../enums/common.enum';
|
||||
import { LandingPageWidgetKeys } from '../../../enums/CustomizablePage.enum';
|
||||
import { Document } from '../../../generated/entity/docStore/document';
|
||||
import { WidgetConfig } from '../../../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import {
|
||||
getAddWidgetHandler,
|
||||
getLayoutUpdateHandler,
|
||||
getRemoveWidgetHandler,
|
||||
} from '../../../utils/CustomizableLandingPageUtils';
|
||||
import customizePageClassBase from '../../../utils/CustomizePageClassBase';
|
||||
import AddWidgetModal from '../../CustomizableComponents/AddWidgetModal/AddWidgetModal';
|
||||
import EmptyWidgetPlaceholder from '../../CustomizableComponents/EmptyWidgetPlaceholder/EmptyWidgetPlaceholder';
|
||||
import './right-sidebar.less';
|
||||
import { RightSidebarProps } from './RightSidebar.interface';
|
||||
|
||||
const ResponsiveGridLayout = WidthProvider(Responsive);
|
||||
|
||||
const RightSidebar = ({
|
||||
announcements,
|
||||
isAnnouncementLoading,
|
||||
parentLayoutData,
|
||||
isEditView = false,
|
||||
followedData,
|
||||
followedDataCount,
|
||||
isLoadingOwnedData,
|
||||
layoutConfigData,
|
||||
updateParentLayout,
|
||||
resetLayout = false,
|
||||
handleResetLayout,
|
||||
handleSaveCurrentPageLayout,
|
||||
}: RightSidebarProps) => {
|
||||
const [layout, setLayout] = useState<Array<WidgetConfig>>([
|
||||
...(layoutConfigData?.page?.layout ?? []),
|
||||
...(isEditView
|
||||
? [
|
||||
{
|
||||
h: 2.3,
|
||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||
w: 1,
|
||||
x: 0,
|
||||
y: 100,
|
||||
isDraggable: false,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
const [placeholderWidgetKey, setPlaceholderWidgetKey] = useState<string>(
|
||||
LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER
|
||||
);
|
||||
const [isWidgetModalOpen, setIsWidgetModalOpen] = useState<boolean>(false);
|
||||
|
||||
const handlePlaceholderWidgetKey = useCallback((value: string) => {
|
||||
setPlaceholderWidgetKey(value);
|
||||
}, []);
|
||||
|
||||
const handleOpenAddWidgetModal = useCallback(() => {
|
||||
setIsWidgetModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleCloseAddWidgetModal = useCallback(() => {
|
||||
setIsWidgetModalOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleRemoveWidget = useCallback((widgetKey: string) => {
|
||||
setLayout(getRemoveWidgetHandler(widgetKey, 2.3, 2.5));
|
||||
}, []);
|
||||
|
||||
const handleAddWidget = useCallback(
|
||||
(
|
||||
newWidgetData: Document,
|
||||
placeholderWidgetKey: string,
|
||||
widgetSize: number
|
||||
) => {
|
||||
setLayout(
|
||||
getAddWidgetHandler(
|
||||
newWidgetData,
|
||||
placeholderWidgetKey,
|
||||
widgetSize,
|
||||
customizePageClassBase.landingPageRightContainerMaxGridSize
|
||||
)
|
||||
);
|
||||
setIsWidgetModalOpen(false);
|
||||
},
|
||||
[layout]
|
||||
);
|
||||
|
||||
const getWidgetFromKey = useCallback(
|
||||
(widgetConfig: WidgetConfig) => {
|
||||
if (widgetConfig.i.endsWith('.EmptyWidgetPlaceholder')) {
|
||||
return (
|
||||
<div className="h-full">
|
||||
<EmptyWidgetPlaceholder
|
||||
handleOpenAddWidgetModal={handleOpenAddWidgetModal}
|
||||
handlePlaceholderWidgetKey={handlePlaceholderWidgetKey}
|
||||
handleRemoveWidget={handleRemoveWidget}
|
||||
iconHeight={SIZE.SMALL}
|
||||
iconWidth={SIZE.SMALL}
|
||||
isEditable={widgetConfig.isDraggable}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||
|
||||
return (
|
||||
<Widget
|
||||
announcements={announcements}
|
||||
followedData={followedData ?? []}
|
||||
followedDataCount={followedDataCount}
|
||||
handleRemoveWidget={handleRemoveWidget}
|
||||
isEditView={isEditView}
|
||||
isLoadingOwnedData={isLoadingOwnedData}
|
||||
selectedGridSize={widgetConfig.w}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[
|
||||
announcements,
|
||||
followedData,
|
||||
followedDataCount,
|
||||
isLoadingOwnedData,
|
||||
isEditView,
|
||||
handleRemoveWidget,
|
||||
handleOpenAddWidgetModal,
|
||||
handlePlaceholderWidgetKey,
|
||||
]
|
||||
);
|
||||
|
||||
const widgets = useMemo(
|
||||
() =>
|
||||
layout
|
||||
.filter((widget: WidgetConfig) =>
|
||||
!isAnnouncementLoading &&
|
||||
widget.i.startsWith(LandingPageWidgetKeys.ANNOUNCEMENTS) &&
|
||||
!isEditView
|
||||
? !isEmpty(announcements)
|
||||
: true
|
||||
)
|
||||
.map((widget: WidgetConfig) => (
|
||||
<div data-grid={widget} key={widget.i}>
|
||||
{getWidgetFromKey(widget)}
|
||||
</div>
|
||||
)),
|
||||
[layout, announcements, getWidgetFromKey, isEditView, isAnnouncementLoading]
|
||||
);
|
||||
|
||||
const handleLayoutUpdate = useCallback(
|
||||
(updatedLayout: Layout[]) => {
|
||||
if (!isEmpty(layout) && !isEmpty(updatedLayout)) {
|
||||
setLayout(getLayoutUpdateHandler(updatedLayout));
|
||||
}
|
||||
},
|
||||
[layout]
|
||||
);
|
||||
|
||||
const addedWidgetsList = useMemo(
|
||||
() =>
|
||||
layout
|
||||
.filter((widget) => widget.i.startsWith('KnowledgePanel'))
|
||||
.map((widget) => widget.i),
|
||||
[layout]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isEditView && !isUndefined(updateParentLayout)) {
|
||||
updateParentLayout(
|
||||
(parentLayoutData ?? []).map((widget) => {
|
||||
if (widget.i === LandingPageWidgetKeys.RIGHT_PANEL) {
|
||||
return {
|
||||
...widget,
|
||||
data: {
|
||||
page: {
|
||||
layout: uniqBy(
|
||||
layout.filter(
|
||||
(widget) => !widget.i.endsWith('.EmptyWidgetPlaceholder')
|
||||
),
|
||||
'i'
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return widget;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [layout]);
|
||||
|
||||
useEffect(() => {
|
||||
if (resetLayout && handleResetLayout && handleSaveCurrentPageLayout) {
|
||||
setLayout([
|
||||
...customizePageClassBase.rightPanelDefaultLayout,
|
||||
...(isEditView
|
||||
? [
|
||||
{
|
||||
h: 2.3,
|
||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||
w: 1,
|
||||
x: 0,
|
||||
y: 100,
|
||||
isDraggable: false,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
handleResetLayout(false);
|
||||
handleSaveCurrentPageLayout(true);
|
||||
}
|
||||
}, [resetLayout]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ResponsiveGridLayout
|
||||
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
|
||||
cols={{ lg: 1, md: 1, sm: 1, xs: 1, xxs: 1 }}
|
||||
containerPadding={[0, customizePageClassBase.landingPageWidgetMargin]}
|
||||
draggableHandle=".drag-widget-icon"
|
||||
isResizable={false}
|
||||
margin={[
|
||||
customizePageClassBase.landingPageWidgetMargin,
|
||||
customizePageClassBase.landingPageWidgetMargin,
|
||||
]}
|
||||
rowHeight={customizePageClassBase.landingPageRowHeight}
|
||||
onLayoutChange={handleLayoutUpdate}>
|
||||
{widgets}
|
||||
</ResponsiveGridLayout>
|
||||
{isWidgetModalOpen && (
|
||||
<AddWidgetModal
|
||||
addedWidgetsList={addedWidgetsList}
|
||||
handleAddWidget={handleAddWidget}
|
||||
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
||||
maxGridSizeSupport={
|
||||
customizePageClassBase.landingPageRightContainerMaxGridSize
|
||||
}
|
||||
open={isWidgetModalOpen}
|
||||
placeholderWidgetKey={placeholderWidgetKey}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RightSidebar;
|
||||
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 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 { Thread } from '../../../generated/entity/feed/thread';
|
||||
import { EntityReference } from '../../../generated/entity/type';
|
||||
import { WidgetConfig } from '../../../pages/CustomizablePage/CustomizablePage.interface';
|
||||
|
||||
export interface RightSidebarProps {
|
||||
isEditView?: boolean;
|
||||
resetLayout?: boolean;
|
||||
handleResetLayout?: (value: boolean) => void;
|
||||
announcements: Thread[];
|
||||
isAnnouncementLoading: boolean;
|
||||
followedDataCount: number;
|
||||
followedData: Array<EntityReference>;
|
||||
isLoadingOwnedData: boolean;
|
||||
layoutConfigData?: WidgetConfig['data'];
|
||||
parentLayoutData?: Array<WidgetConfig>;
|
||||
updateParentLayout?: (newLayout: Array<WidgetConfig>) => void;
|
||||
handleSaveCurrentPageLayout?: (value: boolean) => void;
|
||||
}
|
||||
@ -33,7 +33,7 @@ import { getCountBadge, getEntityDetailLink } from '../../../utils/CommonUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
||||
import FeedsFilterPopover from '../../common/FeedsFilterPopover/FeedsFilterPopover.component';
|
||||
import './feeds-widget.less';
|
||||
import './FeedsWidget.less';
|
||||
|
||||
const FeedsWidget = ({
|
||||
isEditView = false,
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import url('../../styles/variables.less');
|
||||
@import url('../../../styles/variables.less');
|
||||
|
||||
.right-panel-heading {
|
||||
margin-bottom: 8px !important;
|
||||
@ -12,18 +12,21 @@
|
||||
*/
|
||||
|
||||
import { CloseOutlined, DragOutlined } from '@ant-design/icons';
|
||||
import { Button, Col, Row, Space, Typography } from 'antd';
|
||||
import { Button, Card, Col, Row, Space, Typography } from 'antd';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import EntityListSkeleton from '../../components/Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component';
|
||||
import { EntityReference } from '../../generated/type/entityReference';
|
||||
import { WidgetCommonProps } from '../../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import { getRecentlyViewedData, prepareLabel } from '../../utils/CommonUtils';
|
||||
import { getEntityName } from '../../utils/EntityUtils';
|
||||
import { getEntityIcon, getEntityLink } from '../../utils/TableUtils';
|
||||
import './recently-viewed.less';
|
||||
import { EntityReference } from '../../../generated/type/entityReference';
|
||||
import { WidgetCommonProps } from '../../../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import {
|
||||
getRecentlyViewedData,
|
||||
prepareLabel,
|
||||
} from '../../../utils/CommonUtils';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getEntityIcon, getEntityLink } from '../../../utils/TableUtils';
|
||||
import EntityListSkeleton from '../../Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component';
|
||||
import './RecentlyViewed.less';
|
||||
|
||||
const RecentlyViewed = ({
|
||||
isEditView,
|
||||
@ -63,7 +66,9 @@ const RecentlyViewed = ({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="bg-white h-full" data-testid="recently-viewed-container">
|
||||
<Card
|
||||
className="card-widget h-full"
|
||||
data-testid="recently-viewed-container">
|
||||
<EntityListSkeleton
|
||||
dataLength={data.length !== 0 ? data.length : 5}
|
||||
loading={Boolean(isLoading)}>
|
||||
@ -127,7 +132,7 @@ const RecentlyViewed = ({
|
||||
</div>
|
||||
</>
|
||||
</EntityListSkeleton>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@ -30,6 +30,9 @@ interface PageLayoutProp extends HTMLAttributes<HTMLDivElement> {
|
||||
rightPanel?: ReactNode;
|
||||
center?: boolean;
|
||||
pageTitle: string;
|
||||
headerClassName?: string;
|
||||
mainContainerClassName?: string;
|
||||
pageContainerStyle?: React.CSSProperties;
|
||||
rightPanelWidth?: number;
|
||||
leftPanelWidth?: number;
|
||||
}
|
||||
@ -53,6 +56,9 @@ const PageLayoutV1: FC<PageLayoutProp> = ({
|
||||
center = false,
|
||||
leftPanelWidth = 230,
|
||||
rightPanelWidth = 284,
|
||||
headerClassName = '',
|
||||
mainContainerClassName = '',
|
||||
pageContainerStyle = {},
|
||||
}: PageLayoutProp) => {
|
||||
const contentWidth = useMemo(() => {
|
||||
if (leftPanel && rightPanel) {
|
||||
@ -71,17 +77,20 @@ const PageLayoutV1: FC<PageLayoutProp> = ({
|
||||
<DocumentTitle title={pageTitle} />
|
||||
{header && (
|
||||
<div
|
||||
className={classNames({
|
||||
'header-center': center,
|
||||
'm-t-md p-x-md': !center,
|
||||
})}>
|
||||
className={classNames(
|
||||
{
|
||||
'header-center': center,
|
||||
'm-t-md p-x-md': !center,
|
||||
},
|
||||
headerClassName
|
||||
)}>
|
||||
{header}
|
||||
</div>
|
||||
)}
|
||||
<Row
|
||||
className={classNames(className, 'bg-white')}
|
||||
data-testid="page-layout-v1"
|
||||
style={pageContainerStyles}>
|
||||
style={{ ...pageContainerStyles, ...pageContainerStyle }}>
|
||||
{leftPanel && (
|
||||
<Col
|
||||
className="page-layout-leftpanel"
|
||||
@ -95,7 +104,8 @@ const PageLayoutV1: FC<PageLayoutProp> = ({
|
||||
'page-layout-v1-center p-t-sm page-layout-v1-vertical-scroll',
|
||||
{
|
||||
'flex justify-center': center,
|
||||
}
|
||||
},
|
||||
mainContainerClassName
|
||||
)}
|
||||
flex={contentWidth}
|
||||
offset={center ? 3 : 0}
|
||||
|
||||
@ -165,7 +165,9 @@ export const PAGE_HEADERS = {
|
||||
subHeader: i18n.t('message.tools-to-improve-workflow'),
|
||||
},
|
||||
CUSTOM_PAGE: {
|
||||
header: i18n.t('label.customize-landing-page'),
|
||||
header: i18n.t('label.customize-entity', {
|
||||
entity: i18n.t('label.landing-page'),
|
||||
}),
|
||||
subHeader: i18n.t('message.page-sub-header-for-customize-landing-page'),
|
||||
},
|
||||
};
|
||||
|
||||
@ -19,7 +19,6 @@ export enum WidgetWidths {
|
||||
|
||||
export enum LandingPageWidgetKeys {
|
||||
ACTIVITY_FEED = 'KnowledgePanel.ActivityFeed',
|
||||
RIGHT_PANEL = 'Container.RightSidebar',
|
||||
ANNOUNCEMENTS = 'KnowledgePanel.Announcements',
|
||||
FOLLOWING = 'KnowledgePanel.Following',
|
||||
RECENTLY_VIEWED = 'KnowledgePanel.RecentlyViewed',
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "Benutzerdefinierte Eigenschaften",
|
||||
"custom-range": "Benutzerdefinierter Bereich",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "DAG",
|
||||
"dag-view": "DAG-Ansicht",
|
||||
"daily-active-users-on-the-platform": "Täglich aktive Benutzer auf der Plattform",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Schlüsselindikatoren (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "Sprache",
|
||||
"last": "Letzte",
|
||||
"last-error": "Letzter Fehler",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "Custom Properties",
|
||||
"custom-range": "Custom Range",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "Dag",
|
||||
"dag-view": "DAG view",
|
||||
"daily-active-users-on-the-platform": "Daily Active Users on the Platform",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Key Performance Indicators (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "Language",
|
||||
"last": "Last",
|
||||
"last-error": "Last error",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "Propiedades personalizadas",
|
||||
"custom-range": "Custom Range",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "DAG",
|
||||
"dag-view": "Vista DAG",
|
||||
"daily-active-users-on-the-platform": "Usuarios activos diarios en la plataforma",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Indicadores clave de rendimiento (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "Idioma",
|
||||
"last": "Último",
|
||||
"last-error": "Último error",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "Propriétés Personnalisées",
|
||||
"custom-range": "Plage Personnalisée",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "DAG",
|
||||
"dag-view": "Vue DAG",
|
||||
"daily-active-users-on-the-platform": "Utilisateurs Actifs Quotidiens sur la Plateforme",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Indicateurs de Performance Clés (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "Langage",
|
||||
"last": "Dernier·ère",
|
||||
"last-error": "Dernière erreur",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "カスタムプロパティ",
|
||||
"custom-range": "Custom Range",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "Dag",
|
||||
"dag-view": "DAGビュー",
|
||||
"daily-active-users-on-the-platform": "このプラットフォームのアクティブなユーザー",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Key Performance Indicators (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "言語",
|
||||
"last": "最新",
|
||||
"last-error": "最新のエラー",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "Propriedades customizadas",
|
||||
"custom-range": "Custom Range",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "DAG",
|
||||
"dag-view": "Visão da DAG",
|
||||
"daily-active-users-on-the-platform": "Usuários ativos diariamente na plataforma",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Título do KPI",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "Idioma",
|
||||
"last": "Último",
|
||||
"last-error": "Último erro",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "Пользовательские свойства",
|
||||
"custom-range": "Пользовательский диапазон",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "Dag",
|
||||
"dag-view": "Просмотр DAG",
|
||||
"daily-active-users-on-the-platform": "Количество активных пользователей на платформе",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "Ключевой показатель эффективности (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "Язык",
|
||||
"last": "Последний",
|
||||
"last-error": "Последняя ошибка",
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
"custom-property-plural": "自定义属性",
|
||||
"custom-range": "自定义范围",
|
||||
"customise": "Customise",
|
||||
"customize-landing-page": "Customize Landing Page",
|
||||
"customize-entity": "Customize {{entity}}",
|
||||
"dag": "DAG",
|
||||
"dag-view": "DAG 视图",
|
||||
"daily-active-users-on-the-platform": "平台上的每日活跃用户",
|
||||
@ -536,6 +536,7 @@
|
||||
"kpi-title": "关键绩效指标 (KPI)",
|
||||
"kpi-uppercase": "KPI",
|
||||
"kpi-uppercase-plural": "KPIs",
|
||||
"landing-page": "Landing Page",
|
||||
"language": "语言",
|
||||
"last": "最近",
|
||||
"last-error": "最近错误",
|
||||
|
||||
@ -152,7 +152,9 @@ export const CustomPageSettings = () => {
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() => handleCustomisePersona(persona)}>
|
||||
{t('label.customize-landing-page')}
|
||||
{t('label.customize-entity', {
|
||||
entity: t('label.landing-page'),
|
||||
})}
|
||||
</Button>
|
||||
}
|
||||
title={getEntityName(persona)}>
|
||||
|
||||
@ -26,7 +26,6 @@ import {
|
||||
getDocumentByFQN,
|
||||
updateDocument,
|
||||
} from '../../rest/DocStoreAPI';
|
||||
import { getFinalLandingPage } from '../../utils/CustomizableLandingPageUtils';
|
||||
import customizePageClassBase from '../../utils/CustomizePageClassBase';
|
||||
import { getDecodedFqn } from '../../utils/StringsUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||
@ -59,27 +58,19 @@ export const CustomizablePage = () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const pageData = await getDocumentByFQN(pageLayoutFQN);
|
||||
const finalPageData = getFinalLandingPage(pageData, true);
|
||||
|
||||
setPage(finalPageData);
|
||||
setEditedPage(finalPageData);
|
||||
setPage(pageData);
|
||||
setEditedPage(pageData);
|
||||
} catch (error) {
|
||||
if ((error as AxiosError).response?.status === ClientErrors.NOT_FOUND) {
|
||||
setPage(
|
||||
getFinalLandingPage(
|
||||
{
|
||||
name: `${decodedPersonaFQN}${decodedPageFQN}`,
|
||||
fullyQualifiedName: getDecodedFqn(pageLayoutFQN),
|
||||
entityType: EntityType.PAGE,
|
||||
data: {
|
||||
page: {
|
||||
layout: customizePageClassBase.landingPageDefaultLayout,
|
||||
},
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
setPage({
|
||||
name: `${decodedPersonaFQN}${decodedPageFQN}`,
|
||||
fullyQualifiedName: getDecodedFqn(pageLayoutFQN),
|
||||
entityType: EntityType.PAGE,
|
||||
data: {
|
||||
page: { layout: customizePageClassBase.defaultLayout },
|
||||
},
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
@ -88,15 +79,14 @@ export const CustomizablePage = () => {
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const finalPage = getFinalLandingPage(editedPage);
|
||||
let response: Document;
|
||||
|
||||
if (page.id) {
|
||||
const jsonPatch = compare(page, finalPage);
|
||||
const jsonPatch = compare(page, editedPage);
|
||||
|
||||
response = await updateDocument(page.id ?? '', jsonPatch);
|
||||
} else {
|
||||
response = await createDocument(finalPage);
|
||||
response = await createDocument(editedPage);
|
||||
}
|
||||
setPage(response);
|
||||
setEditedPage(response);
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, isNil } from 'lodash';
|
||||
import React, {
|
||||
useCallback,
|
||||
@ -22,16 +21,16 @@ import React, {
|
||||
useState,
|
||||
} from 'react';
|
||||
import RGL, { WidthProvider } from 'react-grid-layout';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import AppState from '../../AppState';
|
||||
import ActivityFeedProvider from '../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||
import { useApplicationConfigContext } from '../../components/ApplicationConfigProvider/ApplicationConfigProvider';
|
||||
import { useAuthContext } from '../../components/authentication/auth-provider/AuthProvider';
|
||||
import PageLayoutV1 from '../../components/containers/PageLayoutV1';
|
||||
import Loader from '../../components/Loader/Loader';
|
||||
import RightSidebar from '../../components/MyData/RightSidebar/RightSidebar.component';
|
||||
import WelcomeScreen from '../../components/WelcomeScreen/WelcomeScreen.component';
|
||||
import { LOGGED_IN_USER_STORAGE_KEY } from '../../constants/constants';
|
||||
import { LandingPageWidgetKeys } from '../../enums/CustomizablePage.enum';
|
||||
import { AssetsType, EntityType } from '../../enums/entity.enum';
|
||||
import { Thread } from '../../generated/entity/feed/thread';
|
||||
import { PageType } from '../../generated/system/ui/page';
|
||||
@ -40,6 +39,7 @@ import { useAuth } from '../../hooks/authHooks';
|
||||
import { getDocumentByFQN } from '../../rest/DocStoreAPI';
|
||||
import { getActiveAnnouncement } from '../../rest/feedsAPI';
|
||||
import { getUserById } from '../../rest/userAPI';
|
||||
import { getWidgetFromKey } from '../../utils/CustomizableLandingPageUtils';
|
||||
import customizePageClassBase from '../../utils/CustomizePageClassBase';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import { WidgetConfig } from '../CustomizablePage/CustomizablePage.interface';
|
||||
@ -49,6 +49,7 @@ const ReactGridLayout = WidthProvider(RGL);
|
||||
|
||||
const MyDataPageV1 = () => {
|
||||
const location = useLocation();
|
||||
const { t } = useTranslation();
|
||||
const { isAuthDisabled } = useAuth(location.pathname);
|
||||
const { currentUser } = useAuthContext();
|
||||
const { selectedPersona } = useApplicationConfigContext();
|
||||
@ -82,10 +83,10 @@ const MyDataPageV1 = () => {
|
||||
const pageData = await getDocumentByFQN(pageFQN);
|
||||
setLayout(pageData.data.page.layout);
|
||||
} else {
|
||||
setLayout(customizePageClassBase.landingPageDefaultLayout);
|
||||
setLayout(customizePageClassBase.defaultLayout);
|
||||
}
|
||||
} catch {
|
||||
setLayout(customizePageClassBase.landingPageDefaultLayout);
|
||||
setLayout(customizePageClassBase.defaultLayout);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@ -144,76 +145,33 @@ const MyDataPageV1 = () => {
|
||||
!isEmpty(AppState.userDetails)) &&
|
||||
isNil(followedData)
|
||||
) {
|
||||
fetchMyData().catch(() => {
|
||||
// ignore since error is displayed in toast in the parent promise.
|
||||
// Added block for sonar code smell
|
||||
});
|
||||
fetchMyData();
|
||||
}
|
||||
}, [AppState.userDetails, AppState.users, isAuthDisabled]);
|
||||
|
||||
const getWidgetFromKey = useCallback(
|
||||
(widgetConfig: WidgetConfig) => {
|
||||
if (widgetConfig.i.startsWith(LandingPageWidgetKeys.RIGHT_PANEL)) {
|
||||
return (
|
||||
<div className="h-full border-left p-l-md">
|
||||
<RightSidebar
|
||||
announcements={announcements}
|
||||
followedData={followedData ?? []}
|
||||
followedDataCount={followedDataCount}
|
||||
isAnnouncementLoading={isAnnouncementLoading}
|
||||
isLoadingOwnedData={isLoadingOwnedData}
|
||||
layoutConfigData={widgetConfig.data}
|
||||
parentLayoutData={layout}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||
|
||||
return (
|
||||
<Widget
|
||||
announcements={announcements}
|
||||
followedData={followedData ?? []}
|
||||
followedDataCount={followedDataCount}
|
||||
isLoadingOwnedData={isLoadingOwnedData}
|
||||
selectedGridSize={widgetConfig.w}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
);
|
||||
},
|
||||
const widgets = useMemo(
|
||||
() =>
|
||||
layout.map((widget) => (
|
||||
<div data-grid={widget} key={widget.i}>
|
||||
{getWidgetFromKey({
|
||||
announcements: announcements,
|
||||
followedData: followedData ?? [],
|
||||
followedDataCount: followedDataCount,
|
||||
isLoadingOwnedData: isLoadingOwnedData,
|
||||
widgetConfig: widget,
|
||||
})}
|
||||
</div>
|
||||
)),
|
||||
[
|
||||
layout,
|
||||
isAnnouncementLoading,
|
||||
announcements,
|
||||
followedData,
|
||||
followedDataCount,
|
||||
isLoadingOwnedData,
|
||||
layout,
|
||||
announcements,
|
||||
isAnnouncementLoading,
|
||||
]
|
||||
);
|
||||
|
||||
const widgets = useMemo(
|
||||
() =>
|
||||
layout
|
||||
.filter((widget: WidgetConfig) =>
|
||||
!isAnnouncementLoading &&
|
||||
widget.i.startsWith(LandingPageWidgetKeys.ANNOUNCEMENTS)
|
||||
? !isEmpty(announcements)
|
||||
: true
|
||||
)
|
||||
.map((widget) => (
|
||||
<div
|
||||
className={classNames({
|
||||
'mt--1': widget.i === LandingPageWidgetKeys.RIGHT_PANEL,
|
||||
})}
|
||||
data-grid={widget}
|
||||
key={widget.i}>
|
||||
{getWidgetFromKey(widget)}
|
||||
</div>
|
||||
)),
|
||||
[layout, getWidgetFromKey]
|
||||
);
|
||||
|
||||
const fetchAnnouncements = useCallback(async () => {
|
||||
try {
|
||||
setIsAnnouncementLoading(true);
|
||||
@ -240,8 +198,10 @@ const MyDataPageV1 = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white h-full">
|
||||
<ActivityFeedProvider>
|
||||
<ActivityFeedProvider>
|
||||
<PageLayoutV1
|
||||
mainContainerClassName="p-t-0"
|
||||
pageTitle={t('label.my-data')}>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
@ -258,8 +218,8 @@ const MyDataPageV1 = () => {
|
||||
{widgets}
|
||||
</ReactGridLayout>
|
||||
)}
|
||||
</ActivityFeedProvider>
|
||||
</div>
|
||||
</PageLayoutV1>
|
||||
</ActivityFeedProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
@import url('../../styles/variables.less');
|
||||
|
||||
.page-layout-rightpanel {
|
||||
background-color: @white;
|
||||
border: 1px solid @border-color;
|
||||
border-radius: 0;
|
||||
padding-left: 0 !important;
|
||||
|
||||
@ -333,7 +333,7 @@ export const addToRecentViewed = (eData: RecentlyViewedData): void => {
|
||||
.sort(arraySorterByKey<RecentlyViewedData>('timestamp', true));
|
||||
arrData.unshift(entityData);
|
||||
|
||||
if (arrData.length > 5) {
|
||||
if (arrData.length > 8) {
|
||||
arrData.pop();
|
||||
}
|
||||
recentlyViewed.data = arrData;
|
||||
|
||||
@ -11,21 +11,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
floor,
|
||||
isEmpty,
|
||||
isUndefined,
|
||||
max,
|
||||
maxBy,
|
||||
round,
|
||||
uniqueId,
|
||||
} from 'lodash';
|
||||
import { isEmpty, isUndefined, max, uniqueId } from 'lodash';
|
||||
import React from 'react';
|
||||
import { Layout } from 'react-grid-layout';
|
||||
import EmptyWidgetPlaceholder from '../components/CustomizableComponents/EmptyWidgetPlaceholder/EmptyWidgetPlaceholder';
|
||||
import { SIZE } from '../enums/common.enum';
|
||||
import {
|
||||
LandingPageWidgetKeys,
|
||||
WidgetWidths,
|
||||
} from '../enums/CustomizablePage.enum';
|
||||
import { Document } from '../generated/entity/docStore/document';
|
||||
import { Thread } from '../generated/entity/feed/thread';
|
||||
import { EntityReference } from '../generated/entity/type';
|
||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import customizePageClassBase from './CustomizePageClassBase';
|
||||
|
||||
@ -161,58 +158,81 @@ const getAllWidgetsArray = (layout: WidgetConfig[]) => {
|
||||
return widgetsArray;
|
||||
};
|
||||
|
||||
const getLayoutWithCalculatedRightPanelHeight = (
|
||||
layout: WidgetConfig[],
|
||||
increaseHeight?: boolean
|
||||
) => {
|
||||
const allWidgets = getAllWidgetsArray(layout);
|
||||
const maxHeightsArray = allWidgets.map((widget) => {
|
||||
const widgetHeightAndPos = widget.h + widget.y;
|
||||
const floorHeightAndPosValue = floor(widgetHeightAndPos);
|
||||
export const getWidgetFromKey = ({
|
||||
widgetConfig,
|
||||
handleOpenAddWidgetModal,
|
||||
handlePlaceholderWidgetKey,
|
||||
handleRemoveWidget,
|
||||
announcements,
|
||||
followedDataCount,
|
||||
followedData,
|
||||
isLoadingOwnedData,
|
||||
iconHeight,
|
||||
iconWidth,
|
||||
isEditView,
|
||||
isAnnouncementLoading,
|
||||
}: {
|
||||
widgetConfig: WidgetConfig;
|
||||
handleOpenAddWidgetModal?: () => void;
|
||||
handlePlaceholderWidgetKey?: (key: string) => void;
|
||||
handleRemoveWidget?: (key: string) => void;
|
||||
announcements: Thread[];
|
||||
followedData?: EntityReference[];
|
||||
followedDataCount: number;
|
||||
isLoadingOwnedData: boolean;
|
||||
iconHeight?: SIZE;
|
||||
iconWidth?: SIZE;
|
||||
isEditView?: boolean;
|
||||
isAnnouncementLoading?: boolean;
|
||||
}) => {
|
||||
if (
|
||||
widgetConfig.i.endsWith('.EmptyWidgetPlaceholder') &&
|
||||
!isUndefined(handleOpenAddWidgetModal) &&
|
||||
!isUndefined(handlePlaceholderWidgetKey) &&
|
||||
!isUndefined(handleRemoveWidget)
|
||||
) {
|
||||
return (
|
||||
<EmptyWidgetPlaceholder
|
||||
handleOpenAddWidgetModal={handleOpenAddWidgetModal}
|
||||
handlePlaceholderWidgetKey={handlePlaceholderWidgetKey}
|
||||
handleRemoveWidget={handleRemoveWidget}
|
||||
iconHeight={iconHeight}
|
||||
iconWidth={iconWidth}
|
||||
isEditable={widgetConfig.isDraggable}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const heightOfWidget =
|
||||
widgetHeightAndPos * customizePageClassBase.landingPageRowHeight +
|
||||
(floorHeightAndPosValue + 1) *
|
||||
customizePageClassBase.landingPageWidgetMargin;
|
||||
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||
|
||||
return {
|
||||
h: round(
|
||||
(heightOfWidget + customizePageClassBase.landingPageWidgetMargin) /
|
||||
(customizePageClassBase.landingPageRowHeight +
|
||||
customizePageClassBase.landingPageWidgetMargin),
|
||||
2
|
||||
),
|
||||
height: heightOfWidget,
|
||||
};
|
||||
});
|
||||
|
||||
const maxHeight = maxBy(maxHeightsArray, 'height');
|
||||
|
||||
return layout.map((widget) =>
|
||||
widget.i === LandingPageWidgetKeys.RIGHT_PANEL
|
||||
? {
|
||||
...widget,
|
||||
h: increaseHeight
|
||||
? customizePageClassBase.landingPageRightContainerEditHeight
|
||||
: maxHeight?.h ?? widget.h,
|
||||
}
|
||||
: widget
|
||||
return (
|
||||
<Widget
|
||||
announcements={announcements}
|
||||
followedData={followedData ?? []}
|
||||
followedDataCount={followedDataCount}
|
||||
handleRemoveWidget={handleRemoveWidget}
|
||||
isAnnouncementLoading={isAnnouncementLoading}
|
||||
isEditView={isEditView}
|
||||
isLoadingOwnedData={isLoadingOwnedData}
|
||||
selectedGridSize={widgetConfig.w}
|
||||
widgetKey={widgetConfig.i}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const getFinalLandingPage = (
|
||||
page: Document,
|
||||
increaseHeight?: boolean
|
||||
): Document => {
|
||||
return {
|
||||
...page,
|
||||
data: {
|
||||
page: {
|
||||
layout: getLayoutWithCalculatedRightPanelHeight(
|
||||
page.data.page?.layout ?? [],
|
||||
increaseHeight
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
export const getLayoutWithEmptyWidgetPlaceholder = (
|
||||
layout: WidgetConfig[],
|
||||
emptyWidgetHeight = 2,
|
||||
emptyWidgetWidth = 1
|
||||
) => [
|
||||
...layout,
|
||||
{
|
||||
h: emptyWidgetHeight,
|
||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||
w: emptyWidgetWidth,
|
||||
x: 0,
|
||||
y: 100,
|
||||
isDraggable: false,
|
||||
},
|
||||
];
|
||||
@ -29,9 +29,9 @@ import AnnouncementsWidget, {
|
||||
import FollowingWidget, {
|
||||
FollowingWidgetProps,
|
||||
} from '../components/MyData/RightSidebar/FollowingWidget';
|
||||
import RecentlyViewed from '../components/recently-viewed/RecentlyViewed';
|
||||
import TotalDataAssetsWidget from '../components/TotalDataAssetsWidget/TotalDataAssetsWidget.component';
|
||||
import FeedsWidget from '../components/Widgets/FeedsWidget/FeedsWidget.component';
|
||||
import RecentlyViewed from '../components/Widgets/RecentlyViewed/RecentlyViewed';
|
||||
import {
|
||||
LandingPageWidgetKeys,
|
||||
WidgetWidths,
|
||||
@ -45,49 +45,19 @@ class CustomizePageClassBase {
|
||||
defaultWidgetHeight = 3;
|
||||
landingPageWidgetMargin = 16;
|
||||
landingPageRowHeight = 100;
|
||||
landingPageRightContainerEditHeight = 16;
|
||||
landingPageMaxGridSize = 3;
|
||||
landingPageRightContainerMaxGridSize = 1;
|
||||
|
||||
landingPageWidgetDefaultHeights: Record<string, number> = {
|
||||
activityFeed: 5,
|
||||
rightSidebar: 11.5,
|
||||
announcements: 3.1,
|
||||
following: 2.4,
|
||||
recentlyViewed: 2.1,
|
||||
myData: 3.1,
|
||||
kpi: 3.1,
|
||||
totalAssets: 3.1,
|
||||
activityFeed: 6,
|
||||
announcements: 3,
|
||||
following: 3,
|
||||
recentlyViewed: 3,
|
||||
myData: 3,
|
||||
kpi: 3,
|
||||
totalAssets: 3,
|
||||
};
|
||||
|
||||
rightPanelDefaultLayout: Array<WidgetConfig> = [
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.announcements,
|
||||
i: LandingPageWidgetKeys.ANNOUNCEMENTS,
|
||||
w: 1,
|
||||
x: 0,
|
||||
y: 0,
|
||||
static: false,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.following,
|
||||
i: LandingPageWidgetKeys.FOLLOWING,
|
||||
w: 1,
|
||||
x: 0,
|
||||
y: 1.5,
|
||||
static: false,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.recentlyViewed,
|
||||
i: LandingPageWidgetKeys.RECENTLY_VIEWED,
|
||||
w: 1,
|
||||
x: 0,
|
||||
y: 3,
|
||||
static: false,
|
||||
},
|
||||
];
|
||||
|
||||
landingPageDefaultLayout: Array<WidgetConfig> = [
|
||||
defaultLayout: Array<WidgetConfig> = [
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.activityFeed,
|
||||
i: LandingPageWidgetKeys.ACTIVITY_FEED,
|
||||
@ -96,19 +66,6 @@ class CustomizePageClassBase {
|
||||
y: 0,
|
||||
static: false,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.rightSidebar,
|
||||
i: LandingPageWidgetKeys.RIGHT_PANEL,
|
||||
w: 1,
|
||||
x: 3,
|
||||
y: 0,
|
||||
data: {
|
||||
page: {
|
||||
layout: this.rightPanelDefaultLayout,
|
||||
},
|
||||
},
|
||||
static: true,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.myData,
|
||||
i: LandingPageWidgetKeys.MY_DATA,
|
||||
@ -130,17 +87,37 @@ class CustomizePageClassBase {
|
||||
i: LandingPageWidgetKeys.TOTAL_DATA_ASSETS,
|
||||
w: 3,
|
||||
x: 0,
|
||||
y: 9.1,
|
||||
y: 9,
|
||||
static: false,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.announcements,
|
||||
i: LandingPageWidgetKeys.ANNOUNCEMENTS,
|
||||
w: 1,
|
||||
x: 3,
|
||||
y: 0,
|
||||
static: false,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.following,
|
||||
i: LandingPageWidgetKeys.FOLLOWING,
|
||||
w: 1,
|
||||
x: 3,
|
||||
y: 1.5,
|
||||
static: false,
|
||||
},
|
||||
{
|
||||
h: this.landingPageWidgetDefaultHeights.recentlyViewed,
|
||||
i: LandingPageWidgetKeys.RECENTLY_VIEWED,
|
||||
w: 1,
|
||||
x: 3,
|
||||
y: 3,
|
||||
static: false,
|
||||
},
|
||||
];
|
||||
|
||||
protected updateRightPanelDefaultLayout(layout: Array<WidgetConfig>) {
|
||||
this.rightPanelDefaultLayout = layout;
|
||||
}
|
||||
|
||||
protected updateLandingPageDefaultLayout(layout: Array<WidgetConfig>) {
|
||||
this.landingPageDefaultLayout = layout;
|
||||
protected updateDefaultLayoutLayout(layout: Array<WidgetConfig>) {
|
||||
this.defaultLayout = layout;
|
||||
}
|
||||
|
||||
protected updateLandingPageWidgetDefaultHeights(obj: Record<string, number>) {
|
||||
@ -231,8 +208,6 @@ class CustomizePageClassBase {
|
||||
switch (widgetName) {
|
||||
case 'ActivityFeed':
|
||||
return this.landingPageWidgetDefaultHeights.activityFeed;
|
||||
case 'RightSidebar':
|
||||
return this.landingPageWidgetDefaultHeights.rightSidebar;
|
||||
case 'Announcements':
|
||||
return this.landingPageWidgetDefaultHeights.announcements;
|
||||
case 'Following':
|
||||
|
||||
@ -254,7 +254,9 @@ export const getGlobalSettingsMenuWithPermission = (
|
||||
key: 'openMetadata',
|
||||
items: [
|
||||
{
|
||||
label: i18next.t('label.customize-landing-page'),
|
||||
label: i18next.t('label.customize-entity', {
|
||||
entity: i18next.t('label.landing-page'),
|
||||
}),
|
||||
isProtected: Boolean(isAdminUser),
|
||||
key: 'openMetadata.customizeLandingPage',
|
||||
icon: <CustomDashboardLogoIcon className="w-4 side-panel-icons" />,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user