mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 19:48:17 +00:00
chore(ui): customize landing page improvements (#13557)
* CustomizePageClassBase class improvements * updated the reset button reordered customize page option on setting page * localization change for other languages * added functionality to choose the widget size and updated widget content according to the sizes * styling fix * fixed double API calls on my data page and flakiness in showing loader for feeds widget * fixed code smell
This commit is contained in:
parent
2ef49d52ca
commit
53629c8cc0
@ -19,5 +19,21 @@ export interface AddWidgetModalProps {
|
|||||||
placeholderWidgetKey: string;
|
placeholderWidgetKey: string;
|
||||||
addedWidgetsList: Array<string>;
|
addedWidgetsList: Array<string>;
|
||||||
handleCloseAddWidgetModal: () => void;
|
handleCloseAddWidgetModal: () => void;
|
||||||
handleAddWidget: (widget: Document, widgetKey: string) => void;
|
handleAddWidget: (
|
||||||
|
widget: Document,
|
||||||
|
widgetKey: string,
|
||||||
|
widgetSize: number
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddWidgetTabContentProps {
|
||||||
|
widget: Document;
|
||||||
|
maxGridSizeSupport: number;
|
||||||
|
getAddWidgetHandler: (widget: Document, widgetSize: number) => () => void;
|
||||||
|
widgetSizeOptions: Array<WidgetSizeInfo>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WidgetSizeInfo {
|
||||||
|
label: string;
|
||||||
|
value: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,19 +11,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CheckOutlined, PlusOutlined } from '@ant-design/icons';
|
import { CheckOutlined } from '@ant-design/icons';
|
||||||
import {
|
import { Modal, Space, Tabs, TabsProps } from 'antd';
|
||||||
Button,
|
|
||||||
Col,
|
|
||||||
Image,
|
|
||||||
Modal,
|
|
||||||
Row,
|
|
||||||
Space,
|
|
||||||
Tabs,
|
|
||||||
TabsProps,
|
|
||||||
Tooltip,
|
|
||||||
Typography,
|
|
||||||
} from 'antd';
|
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
@ -32,11 +21,14 @@ import { ERROR_PLACEHOLDER_TYPE } from '../../../enums/common.enum';
|
|||||||
import { WidgetWidths } from '../../../enums/CustomizablePage.enum';
|
import { WidgetWidths } from '../../../enums/CustomizablePage.enum';
|
||||||
import { Document } from '../../../generated/entity/docStore/document';
|
import { Document } from '../../../generated/entity/docStore/document';
|
||||||
import { getAllKnowledgePanels } from '../../../rest/DocStoreAPI';
|
import { getAllKnowledgePanels } from '../../../rest/DocStoreAPI';
|
||||||
import { CustomizePageClassBase } from '../../../utils/CustomizePageClassBase';
|
|
||||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||||
import ErrorPlaceHolder from '../../common/error-with-placeholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from '../../common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
import { AddWidgetModalProps } from './AddWidgetModal.interface';
|
import {
|
||||||
|
AddWidgetModalProps,
|
||||||
|
WidgetSizeInfo,
|
||||||
|
} from './AddWidgetModal.interface';
|
||||||
import './AddWidgetModal.less';
|
import './AddWidgetModal.less';
|
||||||
|
import AddWidgetTabContent from './AddWidgetTabContent';
|
||||||
|
|
||||||
function AddWidgetModal({
|
function AddWidgetModal({
|
||||||
open,
|
open,
|
||||||
@ -62,29 +54,19 @@ function AddWidgetModal({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getAddWidgetHandler = useCallback(
|
const getAddWidgetHandler = useCallback(
|
||||||
(widget: Document) => () => handleAddWidget(widget, placeholderWidgetKey),
|
(widget: Document, widgetSize: number) => () =>
|
||||||
|
handleAddWidget(widget, placeholderWidgetKey, widgetSize),
|
||||||
[handleAddWidget, placeholderWidgetKey]
|
[handleAddWidget, placeholderWidgetKey]
|
||||||
);
|
);
|
||||||
|
|
||||||
const checkAddWidgetValidity = useCallback(
|
|
||||||
(widget: Document) => {
|
|
||||||
const gridSizes = widget.data.gridSizes;
|
|
||||||
const gridSizesInNumbers: Array<number> = gridSizes.map(
|
|
||||||
(size: WidgetWidths) => WidgetWidths[size]
|
|
||||||
);
|
|
||||||
|
|
||||||
return gridSizesInNumbers.every((size) => size <= maxGridSizeSupport);
|
|
||||||
},
|
|
||||||
[widgetsList]
|
|
||||||
);
|
|
||||||
|
|
||||||
const tabItems: TabsProps['items'] = useMemo(
|
const tabItems: TabsProps['items'] = useMemo(
|
||||||
() =>
|
() =>
|
||||||
widgetsList?.map((widget) => {
|
widgetsList?.map((widget) => {
|
||||||
const widgetAddable = checkAddWidgetValidity(widget);
|
const widgetSizeOptions: Array<WidgetSizeInfo> =
|
||||||
const widgetImage = CustomizePageClassBase.getWidgetImageFromKey(
|
widget.data.gridSizes.map((size: WidgetWidths) => ({
|
||||||
widget.fullyQualifiedName
|
label: size,
|
||||||
);
|
value: WidgetWidths[size],
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label: (
|
label: (
|
||||||
@ -102,36 +84,16 @@ function AddWidgetModal({
|
|||||||
),
|
),
|
||||||
key: widget.fullyQualifiedName,
|
key: widget.fullyQualifiedName,
|
||||||
children: (
|
children: (
|
||||||
<Row align="middle" className="h-min-480" justify="center">
|
<AddWidgetTabContent
|
||||||
<Col>
|
getAddWidgetHandler={getAddWidgetHandler}
|
||||||
<Space align="center" direction="vertical">
|
maxGridSizeSupport={maxGridSizeSupport}
|
||||||
<Image className="p-y-md" preview={false} src={widgetImage} />
|
widget={widget}
|
||||||
<Typography.Paragraph className="d-block text-center">
|
widgetSizeOptions={widgetSizeOptions}
|
||||||
{widget.description}
|
/>
|
||||||
</Typography.Paragraph>
|
|
||||||
<Tooltip
|
|
||||||
placement="bottom"
|
|
||||||
title={
|
|
||||||
widgetAddable ? '' : t('message.can-not-add-widget')
|
|
||||||
}>
|
|
||||||
<Button
|
|
||||||
ghost
|
|
||||||
className="p-x-lg m-t-md"
|
|
||||||
data-testid="add-widget-placeholder-button"
|
|
||||||
disabled={!widgetAddable}
|
|
||||||
icon={<PlusOutlined />}
|
|
||||||
type="primary"
|
|
||||||
onClick={getAddWidgetHandler(widget)}>
|
|
||||||
{t('label.add')}
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Space>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
[widgetsList, addedWidgetsList, checkAddWidgetValidity, getAddWidgetHandler]
|
[widgetsList, addedWidgetsList, getAddWidgetHandler, maxGridSizeSupport]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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 { PlusOutlined } from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Col,
|
||||||
|
Image,
|
||||||
|
Radio,
|
||||||
|
RadioChangeEvent,
|
||||||
|
Row,
|
||||||
|
Space,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
} from 'antd';
|
||||||
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import customizePageClassBase from '../../../utils/CustomizePageClassBase';
|
||||||
|
import { AddWidgetTabContentProps } from './AddWidgetModal.interface';
|
||||||
|
|
||||||
|
function AddWidgetTabContent({
|
||||||
|
getAddWidgetHandler,
|
||||||
|
maxGridSizeSupport,
|
||||||
|
widget,
|
||||||
|
widgetSizeOptions,
|
||||||
|
}: Readonly<AddWidgetTabContentProps>) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [selectedWidgetSize, setSelectedWidgetSize] = useState<number>(
|
||||||
|
widgetSizeOptions[0].value
|
||||||
|
);
|
||||||
|
|
||||||
|
const widgetAddable = useMemo(
|
||||||
|
() => selectedWidgetSize <= maxGridSizeSupport,
|
||||||
|
[selectedWidgetSize, maxGridSizeSupport]
|
||||||
|
);
|
||||||
|
|
||||||
|
const widgetImage = useMemo(
|
||||||
|
() =>
|
||||||
|
customizePageClassBase.getWidgetImageFromKey(
|
||||||
|
widget.fullyQualifiedName,
|
||||||
|
selectedWidgetSize
|
||||||
|
),
|
||||||
|
[widget, selectedWidgetSize]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSizeChange = useCallback((e: RadioChangeEvent) => {
|
||||||
|
setSelectedWidgetSize(e.target.value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
|
<Space>
|
||||||
|
<Typography.Text>{`${t('label.size')}:`}</Typography.Text>
|
||||||
|
<Radio.Group
|
||||||
|
defaultValue={selectedWidgetSize}
|
||||||
|
optionType="button"
|
||||||
|
options={widgetSizeOptions}
|
||||||
|
onChange={handleSizeChange}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
<Row className="h-min-480" justify="center">
|
||||||
|
<Col>
|
||||||
|
<Space align="center" direction="vertical">
|
||||||
|
<Image className="p-y-md" preview={false} src={widgetImage} />
|
||||||
|
<Typography.Paragraph className="d-block text-center">
|
||||||
|
{widget.description}
|
||||||
|
</Typography.Paragraph>
|
||||||
|
<Tooltip
|
||||||
|
placement="bottom"
|
||||||
|
title={widgetAddable ? '' : t('message.can-not-add-widget')}>
|
||||||
|
<Button
|
||||||
|
ghost
|
||||||
|
className="p-x-lg m-t-md"
|
||||||
|
data-testid="add-widget-placeholder-button"
|
||||||
|
disabled={!widgetAddable}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
type="primary"
|
||||||
|
onClick={getAddWidgetHandler(widget, selectedWidgetSize)}>
|
||||||
|
{t('label.add')}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddWidgetTabContent;
|
||||||
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Col, Row, Space, Typography } from 'antd';
|
import { Button, Col, Modal, Row, Space, Typography } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isEmpty, isNil, uniqBy } from 'lodash';
|
import { isEmpty, isNil, uniqBy } from 'lodash';
|
||||||
@ -21,12 +21,6 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { Link, useHistory, useLocation, useParams } from 'react-router-dom';
|
import { Link, useHistory, useLocation, useParams } from 'react-router-dom';
|
||||||
import AppState from '../../../AppState';
|
import AppState from '../../../AppState';
|
||||||
import gridBgImg from '../../../assets/img/grid-bg-img.png';
|
import gridBgImg from '../../../assets/img/grid-bg-img.png';
|
||||||
import {
|
|
||||||
LANDING_PAGE_LAYOUT,
|
|
||||||
LANDING_PAGE_MAX_GRID_SIZE,
|
|
||||||
LANDING_PAGE_ROW_HEIGHT,
|
|
||||||
LANDING_PAGE_WIDGET_MARGIN,
|
|
||||||
} from '../../../constants/CustomizePage.constants';
|
|
||||||
import {
|
import {
|
||||||
GlobalSettingOptions,
|
GlobalSettingOptions,
|
||||||
GlobalSettingsMenuCategory,
|
GlobalSettingsMenuCategory,
|
||||||
@ -48,7 +42,7 @@ import {
|
|||||||
getLayoutUpdateHandler,
|
getLayoutUpdateHandler,
|
||||||
getRemoveWidgetHandler,
|
getRemoveWidgetHandler,
|
||||||
} from '../../../utils/CustomizableLandingPageUtils';
|
} from '../../../utils/CustomizableLandingPageUtils';
|
||||||
import { CustomizePageClassBase } from '../../../utils/CustomizePageClassBase';
|
import customizePageClassBase from '../../../utils/CustomizePageClassBase';
|
||||||
import {
|
import {
|
||||||
getPersonaDetailsPath,
|
getPersonaDetailsPath,
|
||||||
getSettingPath,
|
getSettingPath,
|
||||||
@ -75,7 +69,8 @@ function CustomizeMyData({
|
|||||||
const [resetRightPanelLayout, setResetRightPanelLayout] =
|
const [resetRightPanelLayout, setResetRightPanelLayout] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
const [layout, setLayout] = useState<Array<WidgetConfig>>([
|
const [layout, setLayout] = useState<Array<WidgetConfig>>([
|
||||||
...(initialPageData.data?.page?.layout ?? LANDING_PAGE_LAYOUT),
|
...(initialPageData.data?.page?.layout ??
|
||||||
|
customizePageClassBase.landingPageDefaultLayout),
|
||||||
{
|
{
|
||||||
h: 2,
|
h: 2,
|
||||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||||
@ -89,6 +84,7 @@ function CustomizeMyData({
|
|||||||
LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER
|
LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER
|
||||||
);
|
);
|
||||||
const [isWidgetModalOpen, setIsWidgetModalOpen] = useState<boolean>(false);
|
const [isWidgetModalOpen, setIsWidgetModalOpen] = useState<boolean>(false);
|
||||||
|
const [isResetModalOpen, setIsResetModalOpen] = useState<boolean>(false);
|
||||||
const { isAuthDisabled } = useAuth(location.pathname);
|
const { isAuthDisabled } = useAuth(location.pathname);
|
||||||
const [followedData, setFollowedData] = useState<Array<EntityReference>>();
|
const [followedData, setFollowedData] = useState<Array<EntityReference>>();
|
||||||
const [followedDataCount, setFollowedDataCount] = useState(0);
|
const [followedDataCount, setFollowedDataCount] = useState(0);
|
||||||
@ -124,12 +120,17 @@ function CustomizeMyData({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAddWidget = useCallback(
|
const handleAddWidget = useCallback(
|
||||||
(newWidgetData: Document, placeholderWidgetKey: string) => {
|
(
|
||||||
|
newWidgetData: Document,
|
||||||
|
placeholderWidgetKey: string,
|
||||||
|
widgetSize: number
|
||||||
|
) => {
|
||||||
setLayout(
|
setLayout(
|
||||||
getAddWidgetHandler(
|
getAddWidgetHandler(
|
||||||
newWidgetData,
|
newWidgetData,
|
||||||
placeholderWidgetKey,
|
placeholderWidgetKey,
|
||||||
LANDING_PAGE_MAX_GRID_SIZE
|
widgetSize,
|
||||||
|
customizePageClassBase.landingPageMaxGridSize
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
setIsWidgetModalOpen(false);
|
setIsWidgetModalOpen(false);
|
||||||
@ -146,6 +147,14 @@ function CustomizeMyData({
|
|||||||
[layout]
|
[layout]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleOpenResetModal = useCallback(() => {
|
||||||
|
setIsResetModalOpen(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleCloseResetModal = useCallback(() => {
|
||||||
|
setIsResetModalOpen(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleOpenAddWidgetModal = useCallback(() => {
|
const handleOpenAddWidgetModal = useCallback(() => {
|
||||||
setIsWidgetModalOpen(true);
|
setIsWidgetModalOpen(true);
|
||||||
}, []);
|
}, []);
|
||||||
@ -212,7 +221,7 @@ function CustomizeMyData({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Widget = CustomizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget
|
<Widget
|
||||||
@ -222,6 +231,7 @@ function CustomizeMyData({
|
|||||||
followedDataCount={followedDataCount}
|
followedDataCount={followedDataCount}
|
||||||
handleRemoveWidget={handleRemoveWidget}
|
handleRemoveWidget={handleRemoveWidget}
|
||||||
isLoadingOwnedData={isLoadingOwnedData}
|
isLoadingOwnedData={isLoadingOwnedData}
|
||||||
|
selectedGridSize={widgetConfig.w}
|
||||||
widgetKey={widgetConfig.i}
|
widgetKey={widgetConfig.i}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -315,7 +325,7 @@ function CustomizeMyData({
|
|||||||
|
|
||||||
const handleReset = useCallback(() => {
|
const handleReset = useCallback(() => {
|
||||||
setLayout([
|
setLayout([
|
||||||
...LANDING_PAGE_LAYOUT,
|
...customizePageClassBase.landingPageDefaultLayout,
|
||||||
{
|
{
|
||||||
h: 2,
|
h: 2,
|
||||||
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
i: LandingPageWidgetKeys.EMPTY_WIDGET_PLACEHOLDER,
|
||||||
@ -326,6 +336,7 @@ function CustomizeMyData({
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
setResetRightPanelLayout(true);
|
setResetRightPanelLayout(true);
|
||||||
|
setIsResetModalOpen(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -363,8 +374,8 @@ function CustomizeMyData({
|
|||||||
<Button size="small" onClick={handleCancel}>
|
<Button size="small" onClick={handleCancel}>
|
||||||
{t('label.cancel')}
|
{t('label.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" onClick={handleReset}>
|
<Button size="small" onClick={handleOpenResetModal}>
|
||||||
{t('label.reset-default-layout')}
|
{t('label.reset')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" type="primary" onClick={handleSave}>
|
<Button size="small" type="primary" onClick={handleSave}>
|
||||||
{t('label.save')}
|
{t('label.save')}
|
||||||
@ -380,8 +391,11 @@ function CustomizeMyData({
|
|||||||
cols={{ lg: 4, md: 4, sm: 4, xs: 4, xxs: 4 }}
|
cols={{ lg: 4, md: 4, sm: 4, xs: 4, xxs: 4 }}
|
||||||
draggableHandle=".drag-widget-icon"
|
draggableHandle=".drag-widget-icon"
|
||||||
isResizable={false}
|
isResizable={false}
|
||||||
margin={[LANDING_PAGE_WIDGET_MARGIN, LANDING_PAGE_WIDGET_MARGIN]}
|
margin={[
|
||||||
rowHeight={LANDING_PAGE_ROW_HEIGHT}
|
customizePageClassBase.landingPageWidgetMargin,
|
||||||
|
customizePageClassBase.landingPageWidgetMargin,
|
||||||
|
]}
|
||||||
|
rowHeight={customizePageClassBase.landingPageRowHeight}
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url(${gridBgImg})`,
|
backgroundImage: `url(${gridBgImg})`,
|
||||||
}}
|
}}
|
||||||
@ -393,11 +407,23 @@ function CustomizeMyData({
|
|||||||
addedWidgetsList={addedWidgetsList}
|
addedWidgetsList={addedWidgetsList}
|
||||||
handleAddWidget={handleAddWidget}
|
handleAddWidget={handleAddWidget}
|
||||||
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
||||||
maxGridSizeSupport={LANDING_PAGE_MAX_GRID_SIZE}
|
maxGridSizeSupport={customizePageClassBase.landingPageMaxGridSize}
|
||||||
open={isWidgetModalOpen}
|
open={isWidgetModalOpen}
|
||||||
placeholderWidgetKey={placeholderWidgetKey}
|
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>
|
</ActivityFeedProvider>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import {
|
|||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
import { KPI_WIDGET_GRAPH_COLORS } from '../../constants/DataInsight.constants';
|
import { KPI_WIDGET_GRAPH_COLORS } from '../../constants/DataInsight.constants';
|
||||||
import { DATA_INSIGHT_DOCS } from '../../constants/docs.constants';
|
import { DATA_INSIGHT_DOCS } from '../../constants/docs.constants';
|
||||||
|
import { WidgetWidths } from '../../enums/CustomizablePage.enum';
|
||||||
import { Kpi, KpiResult } from '../../generated/dataInsight/kpi/kpi';
|
import { Kpi, KpiResult } from '../../generated/dataInsight/kpi/kpi';
|
||||||
import { UIKpiResult } from '../../interface/data-insight.interface';
|
import { UIKpiResult } from '../../interface/data-insight.interface';
|
||||||
import {
|
import {
|
||||||
@ -88,6 +89,7 @@ const KPIWidget = ({
|
|||||||
selectedDays = CHART_WIDGET_DAYS_DURATION,
|
selectedDays = CHART_WIDGET_DAYS_DURATION,
|
||||||
handleRemoveWidget,
|
handleRemoveWidget,
|
||||||
widgetKey,
|
widgetKey,
|
||||||
|
selectedGridSize = WidgetWidths.medium,
|
||||||
}: KPIWidgetProps) => {
|
}: KPIWidgetProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [kpiList, setKpiList] = useState<Array<Kpi>>([]);
|
const [kpiList, setKpiList] = useState<Array<Kpi>>([]);
|
||||||
@ -187,6 +189,11 @@ const KPIWidget = ({
|
|||||||
!isUndefined(handleRemoveWidget) && handleRemoveWidget(widgetKey);
|
!isUndefined(handleRemoveWidget) && handleRemoveWidget(widgetKey);
|
||||||
}, [widgetKey]);
|
}, [widgetKey]);
|
||||||
|
|
||||||
|
const isWidgetSizeMedium = useMemo(
|
||||||
|
() => selectedGridSize === WidgetWidths.medium,
|
||||||
|
[selectedGridSize]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchKpiList().catch(() => {
|
fetchKpiList().catch(() => {
|
||||||
// catch handled in parent function
|
// catch handled in parent function
|
||||||
@ -211,34 +218,38 @@ const KPIWidget = ({
|
|||||||
data-testid="kpi-card"
|
data-testid="kpi-card"
|
||||||
id="kpi-charts"
|
id="kpi-charts"
|
||||||
loading={isKPIListLoading || isLoading}>
|
loading={isKPIListLoading || isLoading}>
|
||||||
|
<Row justify="end">
|
||||||
|
<Col>
|
||||||
|
{isEditView && (
|
||||||
|
<Space align="center">
|
||||||
|
<DragOutlined
|
||||||
|
className="drag-widget-icon cursor-pointer"
|
||||||
|
size={14}
|
||||||
|
/>
|
||||||
|
<CloseOutlined size={14} onClick={handleCloseClick} />
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row align="middle" justify="space-between">
|
<Row align="middle" justify="space-between">
|
||||||
<Col>
|
<Col>
|
||||||
<Typography.Text className="font-medium">
|
<Typography.Text className="font-medium">
|
||||||
{t('label.kpi-title')}
|
{t('label.kpi-title')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Col>
|
</Col>
|
||||||
{isEditView && (
|
|
||||||
<Space align="center">
|
|
||||||
<DragOutlined
|
|
||||||
className="drag-widget-icon cursor-pointer"
|
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
<CloseOutlined size={14} onClick={handleCloseClick} />
|
|
||||||
</Space>
|
|
||||||
)}
|
|
||||||
</Row>
|
</Row>
|
||||||
{kpiList.length > 0 ? (
|
{kpiList.length > 0 ? (
|
||||||
<Row>
|
<Row className="p-t-md">
|
||||||
{graphData.length ? (
|
{graphData.length ? (
|
||||||
<>
|
<>
|
||||||
<Col span={14}>
|
<Col span={isWidgetSizeMedium ? 14 : 24}>
|
||||||
<ResponsiveContainer debounce={1} height={250} width="100%">
|
<ResponsiveContainer debounce={1} height={250} width="100%">
|
||||||
<LineChart
|
<LineChart
|
||||||
data={graphData}
|
data={graphData}
|
||||||
margin={{
|
margin={{
|
||||||
top: 10,
|
top: 10,
|
||||||
right: 50,
|
right: isWidgetSizeMedium ? 50 : 20,
|
||||||
left: -20,
|
left: -30,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
}}>
|
}}>
|
||||||
<CartesianGrid
|
<CartesianGrid
|
||||||
@ -258,16 +269,18 @@ const KPIWidget = ({
|
|||||||
</LineChart>
|
</LineChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</Col>
|
</Col>
|
||||||
{!isUndefined(kpiLatestResults) && !isEmpty(kpiLatestResults) && (
|
{!isUndefined(kpiLatestResults) &&
|
||||||
<Col span={10}>
|
!isEmpty(kpiLatestResults) &&
|
||||||
<KPILatestResultsV1
|
isWidgetSizeMedium && (
|
||||||
kpiLatestResultsRecord={kpiLatestResults}
|
<Col span={10}>
|
||||||
/>
|
<KPILatestResultsV1
|
||||||
</Col>
|
kpiLatestResultsRecord={kpiLatestResults}
|
||||||
)}
|
/>
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Col className="justify-center" span={24}>
|
<Col span={24}>
|
||||||
<EmptyPlaceholder />
|
<EmptyPlaceholder />
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -37,6 +37,7 @@ const MyDataWidgetInternal = ({
|
|||||||
const currentUserDetails = AppState.getCurrentUserDetails();
|
const currentUserDetails = AppState.getCurrentUserDetails();
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [data, setData] = useState<EntityReference[]>([]);
|
const [data, setData] = useState<EntityReference[]>([]);
|
||||||
|
const [totalOwnedAssetsCount, setTotalOwnedAssetsCount] = useState<number>(0);
|
||||||
|
|
||||||
const fetchMyDataAssets = async () => {
|
const fetchMyDataAssets = async () => {
|
||||||
if (!currentUserDetails || !currentUserDetails.id) {
|
if (!currentUserDetails || !currentUserDetails.id) {
|
||||||
@ -54,7 +55,8 @@ const MyDataWidgetInternal = ({
|
|||||||
includeData.includes(data.type as AssetsType)
|
includeData.includes(data.type as AssetsType)
|
||||||
);
|
);
|
||||||
|
|
||||||
setData(includedOwnsData.slice(0, 8));
|
setData(includedOwnsData.slice(0, 9));
|
||||||
|
setTotalOwnedAssetsCount(includedOwnsData.length);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setData([]);
|
setData([]);
|
||||||
@ -87,7 +89,7 @@ const MyDataWidgetInternal = ({
|
|||||||
<span className="text-grey-muted font-normal text-xs">
|
<span className="text-grey-muted font-normal text-xs">
|
||||||
{t('label.view-all')}{' '}
|
{t('label.view-all')}{' '}
|
||||||
<span data-testid="my-data-total-count">
|
<span data-testid="my-data-total-count">
|
||||||
{`(${data.length})`}
|
{`(${totalOwnedAssetsCount})`}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ function AnnouncementsWidget({
|
|||||||
}, [widgetKey]);
|
}, [widgetKey]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white h-full">
|
<div className="bg-white h-max-full overflow-y-scroll">
|
||||||
<Row justify="space-between">
|
<Row justify="space-between">
|
||||||
<Col>
|
<Col>
|
||||||
<Typography.Paragraph className="right-panel-label m-b-sm">
|
<Typography.Paragraph className="right-panel-label m-b-sm">
|
||||||
|
|||||||
@ -13,12 +13,6 @@
|
|||||||
import { isEmpty, isUndefined, uniqBy } from 'lodash';
|
import { isEmpty, isUndefined, uniqBy } from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { Layout, Responsive, WidthProvider } from 'react-grid-layout';
|
import { Layout, Responsive, WidthProvider } from 'react-grid-layout';
|
||||||
import {
|
|
||||||
LANDING_PAGE_RIGHT_CONTAINER_MAX_GRID_SIZE,
|
|
||||||
LANDING_PAGE_ROW_HEIGHT,
|
|
||||||
LANDING_PAGE_WIDGET_MARGIN,
|
|
||||||
RIGHT_PANEL_LAYOUT,
|
|
||||||
} from '../../../constants/CustomizePage.constants';
|
|
||||||
import { SIZE } from '../../../enums/common.enum';
|
import { SIZE } from '../../../enums/common.enum';
|
||||||
import { LandingPageWidgetKeys } from '../../../enums/CustomizablePage.enum';
|
import { LandingPageWidgetKeys } from '../../../enums/CustomizablePage.enum';
|
||||||
import { Document } from '../../../generated/entity/docStore/document';
|
import { Document } from '../../../generated/entity/docStore/document';
|
||||||
@ -28,7 +22,7 @@ import {
|
|||||||
getLayoutUpdateHandler,
|
getLayoutUpdateHandler,
|
||||||
getRemoveWidgetHandler,
|
getRemoveWidgetHandler,
|
||||||
} from '../../../utils/CustomizableLandingPageUtils';
|
} from '../../../utils/CustomizableLandingPageUtils';
|
||||||
import { CustomizePageClassBase } from '../../../utils/CustomizePageClassBase';
|
import customizePageClassBase from '../../../utils/CustomizePageClassBase';
|
||||||
import AddWidgetModal from '../../CustomizableComponents/AddWidgetModal/AddWidgetModal';
|
import AddWidgetModal from '../../CustomizableComponents/AddWidgetModal/AddWidgetModal';
|
||||||
import EmptyWidgetPlaceholder from '../../CustomizableComponents/EmptyWidgetPlaceholder/EmptyWidgetPlaceholder';
|
import EmptyWidgetPlaceholder from '../../CustomizableComponents/EmptyWidgetPlaceholder/EmptyWidgetPlaceholder';
|
||||||
import './right-sidebar.less';
|
import './right-sidebar.less';
|
||||||
@ -86,12 +80,17 @@ const RightSidebar = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAddWidget = useCallback(
|
const handleAddWidget = useCallback(
|
||||||
(newWidgetData: Document, placeholderWidgetKey: string) => {
|
(
|
||||||
|
newWidgetData: Document,
|
||||||
|
placeholderWidgetKey: string,
|
||||||
|
widgetSize: number
|
||||||
|
) => {
|
||||||
setLayout(
|
setLayout(
|
||||||
getAddWidgetHandler(
|
getAddWidgetHandler(
|
||||||
newWidgetData,
|
newWidgetData,
|
||||||
placeholderWidgetKey,
|
placeholderWidgetKey,
|
||||||
LANDING_PAGE_RIGHT_CONTAINER_MAX_GRID_SIZE
|
widgetSize,
|
||||||
|
customizePageClassBase.landingPageRightContainerMaxGridSize
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
setIsWidgetModalOpen(false);
|
setIsWidgetModalOpen(false);
|
||||||
@ -117,7 +116,7 @@ const RightSidebar = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Widget = CustomizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget
|
<Widget
|
||||||
@ -127,6 +126,7 @@ const RightSidebar = ({
|
|||||||
handleRemoveWidget={handleRemoveWidget}
|
handleRemoveWidget={handleRemoveWidget}
|
||||||
isEditView={isEditView}
|
isEditView={isEditView}
|
||||||
isLoadingOwnedData={isLoadingOwnedData}
|
isLoadingOwnedData={isLoadingOwnedData}
|
||||||
|
selectedGridSize={widgetConfig.w}
|
||||||
widgetKey={widgetConfig.i}
|
widgetKey={widgetConfig.i}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -207,7 +207,7 @@ const RightSidebar = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (resetLayout && handleResetLayout) {
|
if (resetLayout && handleResetLayout) {
|
||||||
setLayout([
|
setLayout([
|
||||||
...RIGHT_PANEL_LAYOUT,
|
...customizePageClassBase.rightPanelDefaultLayout,
|
||||||
...(isEditView
|
...(isEditView
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
@ -230,11 +230,14 @@ const RightSidebar = ({
|
|||||||
<ResponsiveGridLayout
|
<ResponsiveGridLayout
|
||||||
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
|
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
|
||||||
cols={{ lg: 1, md: 1, sm: 1, xs: 1, xxs: 1 }}
|
cols={{ lg: 1, md: 1, sm: 1, xs: 1, xxs: 1 }}
|
||||||
containerPadding={[0, LANDING_PAGE_WIDGET_MARGIN]}
|
containerPadding={[0, customizePageClassBase.landingPageWidgetMargin]}
|
||||||
draggableHandle=".drag-widget-icon"
|
draggableHandle=".drag-widget-icon"
|
||||||
isResizable={false}
|
isResizable={false}
|
||||||
margin={[LANDING_PAGE_WIDGET_MARGIN, LANDING_PAGE_WIDGET_MARGIN]}
|
margin={[
|
||||||
rowHeight={LANDING_PAGE_ROW_HEIGHT}
|
customizePageClassBase.landingPageWidgetMargin,
|
||||||
|
customizePageClassBase.landingPageWidgetMargin,
|
||||||
|
]}
|
||||||
|
rowHeight={customizePageClassBase.landingPageRowHeight}
|
||||||
onLayoutChange={handleLayoutUpdate}>
|
onLayoutChange={handleLayoutUpdate}>
|
||||||
{widgets}
|
{widgets}
|
||||||
</ResponsiveGridLayout>
|
</ResponsiveGridLayout>
|
||||||
@ -243,7 +246,9 @@ const RightSidebar = ({
|
|||||||
addedWidgetsList={addedWidgetsList}
|
addedWidgetsList={addedWidgetsList}
|
||||||
handleAddWidget={handleAddWidget}
|
handleAddWidget={handleAddWidget}
|
||||||
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
handleCloseAddWidgetModal={handleCloseAddWidgetModal}
|
||||||
maxGridSizeSupport={LANDING_PAGE_RIGHT_CONTAINER_MAX_GRID_SIZE}
|
maxGridSizeSupport={
|
||||||
|
customizePageClassBase.landingPageRightContainerMaxGridSize
|
||||||
|
}
|
||||||
open={isWidgetModalOpen}
|
open={isWidgetModalOpen}
|
||||||
placeholderWidgetKey={placeholderWidgetKey}
|
placeholderWidgetKey={placeholderWidgetKey}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -11,9 +11,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
.announcement-container-list {
|
.announcement-container-list {
|
||||||
max-height: 360px;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
.feed-card-body {
|
.feed-card-body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import {
|
|||||||
} from 'recharts';
|
} from 'recharts';
|
||||||
import { CHART_WIDGET_DAYS_DURATION } from '../../constants/constants';
|
import { CHART_WIDGET_DAYS_DURATION } from '../../constants/constants';
|
||||||
import { TOTAL_ENTITY_CHART_COLOR } from '../../constants/DataInsight.constants';
|
import { TOTAL_ENTITY_CHART_COLOR } from '../../constants/DataInsight.constants';
|
||||||
|
import { WidgetWidths } from '../../enums/CustomizablePage.enum';
|
||||||
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
||||||
import {
|
import {
|
||||||
DataInsightChartResult,
|
DataInsightChartResult,
|
||||||
@ -57,6 +58,7 @@ const TotalDataAssetsWidget = ({
|
|||||||
selectedDays = CHART_WIDGET_DAYS_DURATION,
|
selectedDays = CHART_WIDGET_DAYS_DURATION,
|
||||||
handleRemoveWidget,
|
handleRemoveWidget,
|
||||||
widgetKey,
|
widgetKey,
|
||||||
|
selectedGridSize,
|
||||||
}: TotalDataAssetsWidgetProps) => {
|
}: TotalDataAssetsWidgetProps) => {
|
||||||
const [totalEntitiesByType, setTotalEntitiesByType] =
|
const [totalEntitiesByType, setTotalEntitiesByType] =
|
||||||
useState<DataInsightChartResult>();
|
useState<DataInsightChartResult>();
|
||||||
@ -96,6 +98,11 @@ const TotalDataAssetsWidget = ({
|
|||||||
!isUndefined(handleRemoveWidget) && handleRemoveWidget(widgetKey);
|
!isUndefined(handleRemoveWidget) && handleRemoveWidget(widgetKey);
|
||||||
}, [widgetKey]);
|
}, [widgetKey]);
|
||||||
|
|
||||||
|
const isWidgetSizeLarge = useMemo(
|
||||||
|
() => selectedGridSize === WidgetWidths.large,
|
||||||
|
[selectedGridSize]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTotalEntitiesByType();
|
fetchTotalEntitiesByType();
|
||||||
}, [selectedDays]);
|
}, [selectedDays]);
|
||||||
@ -121,18 +128,18 @@ const TotalDataAssetsWidget = ({
|
|||||||
)}
|
)}
|
||||||
{data.length ? (
|
{data.length ? (
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={14}>
|
<Col span={isWidgetSizeLarge ? 14 : 24}>
|
||||||
<Typography.Text className="font-medium">
|
<Typography.Text className="font-medium">
|
||||||
{t('label.data-insight-total-entity-summary')}
|
{t('label.data-insight-total-entity-summary')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<div className="p-t-lg">
|
<div className="p-t-md">
|
||||||
<ResponsiveContainer height={250} width="100%">
|
<ResponsiveContainer height={250} width="100%">
|
||||||
<AreaChart
|
<AreaChart
|
||||||
data={data}
|
data={data}
|
||||||
margin={{
|
margin={{
|
||||||
top: 10,
|
top: 10,
|
||||||
right: 50,
|
right: isWidgetSizeLarge ? 50 : 20,
|
||||||
left: -20,
|
left: -30,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
}}
|
}}
|
||||||
syncId="anyId">
|
syncId="anyId">
|
||||||
@ -152,15 +159,17 @@ const TotalDataAssetsWidget = ({
|
|||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={10}>
|
{isWidgetSizeLarge && (
|
||||||
<TotalEntityInsightSummary
|
<Col span={10}>
|
||||||
entities={entities}
|
<TotalEntityInsightSummary
|
||||||
latestData={latestData}
|
entities={entities}
|
||||||
relativePercentage={relativePercentage}
|
latestData={latestData}
|
||||||
selectedDays={selectedDays}
|
relativePercentage={relativePercentage}
|
||||||
total={total}
|
selectedDays={selectedDays}
|
||||||
/>
|
total={total}
|
||||||
</Col>
|
/>
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
) : (
|
) : (
|
||||||
<Row>
|
<Row>
|
||||||
|
|||||||
@ -16,7 +16,6 @@ import { isUndefined } from 'lodash';
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import AppState from '../../../AppState';
|
|
||||||
import ActivityFeedListV1 from '../../../components/ActivityFeed/ActivityFeedList/ActivityFeedListV1.component';
|
import ActivityFeedListV1 from '../../../components/ActivityFeed/ActivityFeedList/ActivityFeedListV1.component';
|
||||||
import { useActivityFeedProvider } from '../../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
import { useActivityFeedProvider } from '../../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||||
import { ActivityFeedTabs } from '../../../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
|
import { ActivityFeedTabs } from '../../../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
|
||||||
@ -32,6 +31,7 @@ import { WidgetCommonProps } from '../../../pages/CustomizablePage/CustomizableP
|
|||||||
import { getFeedsWithFilter } from '../../../rest/feedsAPI';
|
import { getFeedsWithFilter } from '../../../rest/feedsAPI';
|
||||||
import { getCountBadge, getEntityDetailLink } from '../../../utils/CommonUtils';
|
import { getCountBadge, getEntityDetailLink } from '../../../utils/CommonUtils';
|
||||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||||
|
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
||||||
import FeedsFilterPopover from '../../common/FeedsFilterPopover/FeedsFilterPopover.component';
|
import FeedsFilterPopover from '../../common/FeedsFilterPopover/FeedsFilterPopover.component';
|
||||||
import './feeds-widget.less';
|
import './feeds-widget.less';
|
||||||
|
|
||||||
@ -43,18 +43,16 @@ const FeedsWidget = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { isTourOpen } = useTourProvider();
|
const { isTourOpen } = useTourProvider();
|
||||||
|
const { currentUser } = useAuthContext();
|
||||||
const [activeTab, setActiveTab] = useState<ActivityFeedTabs>(
|
const [activeTab, setActiveTab] = useState<ActivityFeedTabs>(
|
||||||
ActivityFeedTabs.ALL
|
ActivityFeedTabs.ALL
|
||||||
);
|
);
|
||||||
const { loading, entityThread, entityPaging, getFeedData } =
|
const { loading, entityThread, entityPaging, getFeedData } =
|
||||||
useActivityFeedProvider();
|
useActivityFeedProvider();
|
||||||
const [taskCount, setTaskCount] = useState(0);
|
const [taskCount, setTaskCount] = useState(0);
|
||||||
const currentUser = useMemo(
|
|
||||||
() => AppState.getCurrentUserDetails(),
|
|
||||||
[AppState.userDetails, AppState.nonSecureUserDetails]
|
|
||||||
);
|
|
||||||
const [defaultFilter, setDefaultFilter] = useState<FeedFilter>(
|
const [defaultFilter, setDefaultFilter] = useState<FeedFilter>(
|
||||||
FeedFilter.OWNER_OR_FOLLOWS
|
currentUser?.isAdmin ? FeedFilter.ALL : FeedFilter.OWNER_OR_FOLLOWS
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -1,107 +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 { LandingPageWidgetKeys } from '../enums/CustomizablePage.enum';
|
|
||||||
|
|
||||||
export const DEFAULT_WIDGET_HEIGHT = 3;
|
|
||||||
export const LANDING_PAGE_WIDGET_MARGIN = 16;
|
|
||||||
export const LANDING_PAGE_ROW_HEIGHT = 100;
|
|
||||||
export const LANDING_PAGE_RIGHT_CONTAINER_EDIT_HEIGHT = 16;
|
|
||||||
export const LANDING_PAGE_MAX_GRID_SIZE = 3;
|
|
||||||
export const LANDING_PAGE_RIGHT_CONTAINER_MAX_GRID_SIZE = 1;
|
|
||||||
|
|
||||||
export const LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS = {
|
|
||||||
activityFeed: 5,
|
|
||||||
rightSidebar: 11.5,
|
|
||||||
announcements: 3.9,
|
|
||||||
following: 2.4,
|
|
||||||
recentlyViewed: 2.1,
|
|
||||||
myData: 2.8,
|
|
||||||
kpi: 2.8,
|
|
||||||
totalDataAssets: 3.42,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const RIGHT_PANEL_LAYOUT = [
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.announcements,
|
|
||||||
i: LandingPageWidgetKeys.ANNOUNCEMENTS,
|
|
||||||
w: 1,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.following,
|
|
||||||
i: LandingPageWidgetKeys.FOLLOWING,
|
|
||||||
w: 1,
|
|
||||||
x: 0,
|
|
||||||
y: 1.5,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.recentlyViewed,
|
|
||||||
i: LandingPageWidgetKeys.RECENTLY_VIEWED,
|
|
||||||
w: 1,
|
|
||||||
x: 0,
|
|
||||||
y: 3,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const LANDING_PAGE_LAYOUT = [
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.activityFeed,
|
|
||||||
i: LandingPageWidgetKeys.ACTIVITY_FEED,
|
|
||||||
w: 3,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.rightSidebar,
|
|
||||||
i: LandingPageWidgetKeys.RIGHT_PANEL,
|
|
||||||
w: 1,
|
|
||||||
x: 3,
|
|
||||||
y: 0,
|
|
||||||
data: {
|
|
||||||
page: {
|
|
||||||
layout: RIGHT_PANEL_LAYOUT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
static: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.myData,
|
|
||||||
i: LandingPageWidgetKeys.MY_DATA,
|
|
||||||
w: 1,
|
|
||||||
x: 0,
|
|
||||||
y: 6,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.kpi,
|
|
||||||
i: LandingPageWidgetKeys.KPI,
|
|
||||||
w: 2,
|
|
||||||
x: 1,
|
|
||||||
y: 6,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
h: LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.totalDataAssets,
|
|
||||||
i: LandingPageWidgetKeys.TOTAL_DATA_ASSETS,
|
|
||||||
w: 3,
|
|
||||||
x: 0,
|
|
||||||
y: 9.1,
|
|
||||||
static: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Benennen Sie den Namen und die Anzeigebezeichnung für das {{entity}} um.",
|
"rename-entity": "Benennen Sie den Namen und die Anzeigebezeichnung für das {{entity}} um.",
|
||||||
"request-description": "Beschreibung der Anfrage",
|
"request-description": "Beschreibung der Anfrage",
|
||||||
"request-update-description": "Aktualisierung der Anfragebeschreibung",
|
"request-update-description": "Aktualisierung der Anfragebeschreibung",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "Der Zurücksetzungslink wurde an Ihre E-Mail gesendet",
|
"reset-link-has-been-sent": "Der Zurücksetzungslink wurde an Ihre E-Mail gesendet",
|
||||||
"restore-action-description": "Durch das Wiederherstellen dieses {{entityType}} werden seine Metadaten in OpenMetadata wiederhergestellt.",
|
"restore-action-description": "Durch das Wiederherstellen dieses {{entityType}} werden seine Metadaten in OpenMetadata wiederhergestellt.",
|
||||||
"restore-deleted-team": "Das Wiederherstellen des Teams fügt alle Metadaten wieder zu OpenMetadata hinzu.",
|
"restore-deleted-team": "Das Wiederherstellen des Teams fügt alle Metadaten wieder zu OpenMetadata hinzu.",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Rename the Name and Display Name for the {{entity}}.",
|
"rename-entity": "Rename the Name and Display Name for the {{entity}}.",
|
||||||
"request-description": "Request description",
|
"request-description": "Request description",
|
||||||
"request-update-description": "Request update description",
|
"request-update-description": "Request update description",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "Reset link has been sent to your email",
|
"reset-link-has-been-sent": "Reset link has been sent to your email",
|
||||||
"restore-action-description": "Restoring this {{entityType}} will restore its metadata in OpenMetadata.",
|
"restore-action-description": "Restoring this {{entityType}} will restore its metadata in OpenMetadata.",
|
||||||
"restore-deleted-team": " Restoring the Team will add all the metadata back to OpenMetadata",
|
"restore-deleted-team": " Restoring the Team will add all the metadata back to OpenMetadata",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Renombrar el nombre y nombre visualizado para el {{entity}}.",
|
"rename-entity": "Renombrar el nombre y nombre visualizado para el {{entity}}.",
|
||||||
"request-description": "Descripción de la solicitud",
|
"request-description": "Descripción de la solicitud",
|
||||||
"request-update-description": "Descripción de la actualización de la solicitud",
|
"request-update-description": "Descripción de la actualización de la solicitud",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "Se ha enviado un enlace de restablecimiento a tu correo electrónico",
|
"reset-link-has-been-sent": "Se ha enviado un enlace de restablecimiento a tu correo electrónico",
|
||||||
"restore-action-description": "Restaurar este {{entityType}} restaurará sus metadatos en OpenMetadata.",
|
"restore-action-description": "Restaurar este {{entityType}} restaurará sus metadatos en OpenMetadata.",
|
||||||
"restore-deleted-team": "Restaurar el equipo agregará todos los metadatos de nuevo a OpenMetadata",
|
"restore-deleted-team": "Restaurar el equipo agregará todos los metadatos de nuevo a OpenMetadata",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Renommer le nom et le nom d'affichage pour {{entity}}.",
|
"rename-entity": "Renommer le nom et le nom d'affichage pour {{entity}}.",
|
||||||
"request-description": "Demander une description",
|
"request-description": "Demander une description",
|
||||||
"request-update-description": "Mettre à jour la demande de description",
|
"request-update-description": "Mettre à jour la demande de description",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "Lien de réinitialisation a été envoyé à votre adresse e-mail.",
|
"reset-link-has-been-sent": "Lien de réinitialisation a été envoyé à votre adresse e-mail.",
|
||||||
"restore-action-description": "Restaurer cette {{entityType}} restaurera les métadonnées dans OpenMetadata.",
|
"restore-action-description": "Restaurer cette {{entityType}} restaurera les métadonnées dans OpenMetadata.",
|
||||||
"restore-deleted-team": " Restaurer cette Equipe ajoutera toutes les métadonnées dans OpenMetadata",
|
"restore-deleted-team": " Restaurer cette Equipe ajoutera toutes les métadonnées dans OpenMetadata",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Rename the Name and Display Name for the {{entity}}.",
|
"rename-entity": "Rename the Name and Display Name for the {{entity}}.",
|
||||||
"request-description": "Request description",
|
"request-description": "Request description",
|
||||||
"request-update-description": "Request update description",
|
"request-update-description": "Request update description",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "パスワードリセット用のリンクがあなたのメールアドレスに送信されました",
|
"reset-link-has-been-sent": "パスワードリセット用のリンクがあなたのメールアドレスに送信されました",
|
||||||
"restore-action-description": "この{{entityType}}をリストアすると、OpenMetadataのメタデータがリストアされます。",
|
"restore-action-description": "この{{entityType}}をリストアすると、OpenMetadataのメタデータがリストアされます。",
|
||||||
"restore-deleted-team": "チームをリストアすると全てのメタデータがOpenMetadataに戻されます。",
|
"restore-deleted-team": "チームをリストアすると全てのメタデータがOpenMetadataに戻されます。",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Rename the Name and Display Name for the {{entity}}.",
|
"rename-entity": "Rename the Name and Display Name for the {{entity}}.",
|
||||||
"request-description": "Descrição da solicitação",
|
"request-description": "Descrição da solicitação",
|
||||||
"request-update-description": "Atualizar descrição da solicitação",
|
"request-update-description": "Atualizar descrição da solicitação",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "O link de redefinição foi enviado para o seu e-mail",
|
"reset-link-has-been-sent": "O link de redefinição foi enviado para o seu e-mail",
|
||||||
"restore-action-description": "Restaurar esta {{entityType}} irá restaurar seus metadados no OpenMetadata.",
|
"restore-action-description": "Restaurar esta {{entityType}} irá restaurar seus metadados no OpenMetadata.",
|
||||||
"restore-deleted-team": "Restaurar a equipe irá adicionar todos os metadados de volta ao OpenMetadata",
|
"restore-deleted-team": "Restaurar a equipe irá adicionar todos os metadados de volta ao OpenMetadata",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "Измените имя и отображаемое имя для {{entity}}.",
|
"rename-entity": "Измените имя и отображаемое имя для {{entity}}.",
|
||||||
"request-description": "Запросить описание",
|
"request-description": "Запросить описание",
|
||||||
"request-update-description": "Запросить обновление описания",
|
"request-update-description": "Запросить обновление описания",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "Ссылка для сброса отправлена на вашу электронную почту",
|
"reset-link-has-been-sent": "Ссылка для сброса отправлена на вашу электронную почту",
|
||||||
"restore-action-description": "Восстановление этого {{entityType}} восстановит его метаданные в OpenMetadata.",
|
"restore-action-description": "Восстановление этого {{entityType}} восстановит его метаданные в OpenMetadata.",
|
||||||
"restore-deleted-team": "Восстановление команды добавит все метаданные обратно в OpenMetadata.",
|
"restore-deleted-team": "Восстановление команды добавит все метаданные обратно в OpenMetadata.",
|
||||||
|
|||||||
@ -1467,6 +1467,7 @@
|
|||||||
"rename-entity": "修改{{entity}}的名称和显示名",
|
"rename-entity": "修改{{entity}}的名称和显示名",
|
||||||
"request-description": "请求详细描述",
|
"request-description": "请求详细描述",
|
||||||
"request-update-description": "请求更新描述",
|
"request-update-description": "请求更新描述",
|
||||||
|
"reset-layout-confirmation": "Are you sure you want to apply the \"Default Layout\"?",
|
||||||
"reset-link-has-been-sent": "重置链接已发送到您的电子邮箱",
|
"reset-link-has-been-sent": "重置链接已发送到您的电子邮箱",
|
||||||
"restore-action-description": "还原此{{entityType}}将在 OpenMetadata 中还原其元数据",
|
"restore-action-description": "还原此{{entityType}}将在 OpenMetadata 中还原其元数据",
|
||||||
"restore-deleted-team": "还原团队将会把所有元数据添加回 OpenMetadata",
|
"restore-deleted-team": "还原团队将会把所有元数据添加回 OpenMetadata",
|
||||||
|
|||||||
@ -23,6 +23,7 @@ export interface WidgetConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface WidgetCommonProps {
|
export interface WidgetCommonProps {
|
||||||
|
selectedGridSize?: number;
|
||||||
isEditView?: boolean;
|
isEditView?: boolean;
|
||||||
widgetKey: string;
|
widgetKey: string;
|
||||||
handleRemoveWidget?: (widgetKey: string) => void;
|
handleRemoveWidget?: (widgetKey: string) => void;
|
||||||
|
|||||||
@ -16,7 +16,6 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import CustomizeMyData from '../../components/CustomizableComponents/CustomizeMyData/CustomizeMyData';
|
import CustomizeMyData from '../../components/CustomizableComponents/CustomizeMyData/CustomizeMyData';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
import { LANDING_PAGE_LAYOUT } from '../../constants/CustomizePage.constants';
|
|
||||||
import { ClientErrors } from '../../enums/axios.enum';
|
import { ClientErrors } from '../../enums/axios.enum';
|
||||||
import { EntityType } from '../../enums/entity.enum';
|
import { EntityType } from '../../enums/entity.enum';
|
||||||
import { Document } from '../../generated/entity/docStore/document';
|
import { Document } from '../../generated/entity/docStore/document';
|
||||||
@ -27,6 +26,7 @@ import {
|
|||||||
updateDocument,
|
updateDocument,
|
||||||
} from '../../rest/DocStoreAPI';
|
} from '../../rest/DocStoreAPI';
|
||||||
import { getFinalLandingPage } from '../../utils/CustomizableLandingPageUtils';
|
import { getFinalLandingPage } from '../../utils/CustomizableLandingPageUtils';
|
||||||
|
import customizePageClassBase from '../../utils/CustomizePageClassBase';
|
||||||
|
|
||||||
export const CustomizablePage = () => {
|
export const CustomizablePage = () => {
|
||||||
const { fqn, pageFqn } = useParams<{ fqn: string; pageFqn: PageType }>();
|
const { fqn, pageFqn } = useParams<{ fqn: string; pageFqn: PageType }>();
|
||||||
@ -57,7 +57,7 @@ export const CustomizablePage = () => {
|
|||||||
entityType: EntityType.PAGE,
|
entityType: EntityType.PAGE,
|
||||||
data: {
|
data: {
|
||||||
page: {
|
page: {
|
||||||
layout: LANDING_PAGE_LAYOUT,
|
layout: customizePageClassBase.landingPageDefaultLayout,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -31,10 +31,6 @@ import Loader from '../../components/Loader/Loader';
|
|||||||
import RightSidebar from '../../components/MyData/RightSidebar/RightSidebar.component';
|
import RightSidebar from '../../components/MyData/RightSidebar/RightSidebar.component';
|
||||||
import WelcomeScreen from '../../components/WelcomeScreen/WelcomeScreen.component';
|
import WelcomeScreen from '../../components/WelcomeScreen/WelcomeScreen.component';
|
||||||
import { LOGGED_IN_USER_STORAGE_KEY } from '../../constants/constants';
|
import { LOGGED_IN_USER_STORAGE_KEY } from '../../constants/constants';
|
||||||
import {
|
|
||||||
LANDING_PAGE_LAYOUT,
|
|
||||||
LANDING_PAGE_WIDGET_MARGIN,
|
|
||||||
} from '../../constants/CustomizePage.constants';
|
|
||||||
import { LandingPageWidgetKeys } from '../../enums/CustomizablePage.enum';
|
import { LandingPageWidgetKeys } from '../../enums/CustomizablePage.enum';
|
||||||
import { AssetsType, EntityType } from '../../enums/entity.enum';
|
import { AssetsType, EntityType } from '../../enums/entity.enum';
|
||||||
import { Thread } from '../../generated/entity/feed/thread';
|
import { Thread } from '../../generated/entity/feed/thread';
|
||||||
@ -44,7 +40,7 @@ import { useAuth } from '../../hooks/authHooks';
|
|||||||
import { getDocumentByFQN } from '../../rest/DocStoreAPI';
|
import { getDocumentByFQN } from '../../rest/DocStoreAPI';
|
||||||
import { getActiveAnnouncement } from '../../rest/feedsAPI';
|
import { getActiveAnnouncement } from '../../rest/feedsAPI';
|
||||||
import { getUserById } from '../../rest/userAPI';
|
import { getUserById } from '../../rest/userAPI';
|
||||||
import { CustomizePageClassBase } from '../../utils/CustomizePageClassBase';
|
import customizePageClassBase from '../../utils/CustomizePageClassBase';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
import { WidgetConfig } from '../CustomizablePage/CustomizablePage.interface';
|
import { WidgetConfig } from '../CustomizablePage/CustomizablePage.interface';
|
||||||
import './my-data.less';
|
import './my-data.less';
|
||||||
@ -86,10 +82,10 @@ const MyDataPageV1 = () => {
|
|||||||
const pageData = await getDocumentByFQN(pageFQN);
|
const pageData = await getDocumentByFQN(pageFQN);
|
||||||
setLayout(pageData.data.page.layout);
|
setLayout(pageData.data.page.layout);
|
||||||
} else {
|
} else {
|
||||||
setLayout(LANDING_PAGE_LAYOUT);
|
setLayout(customizePageClassBase.landingPageDefaultLayout);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
setLayout(LANDING_PAGE_LAYOUT);
|
setLayout(customizePageClassBase.landingPageDefaultLayout);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@ -173,7 +169,7 @@ const MyDataPageV1 = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Widget = CustomizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
const Widget = customizePageClassBase.getWidgetsFromKey(widgetConfig.i);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget
|
<Widget
|
||||||
@ -181,6 +177,7 @@ const MyDataPageV1 = () => {
|
|||||||
followedData={followedData ?? []}
|
followedData={followedData ?? []}
|
||||||
followedDataCount={followedDataCount}
|
followedDataCount={followedDataCount}
|
||||||
isLoadingOwnedData={isLoadingOwnedData}
|
isLoadingOwnedData={isLoadingOwnedData}
|
||||||
|
selectedGridSize={widgetConfig.w}
|
||||||
widgetKey={widgetConfig.i}
|
widgetKey={widgetConfig.i}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -255,7 +252,10 @@ const MyDataPageV1 = () => {
|
|||||||
cols={{ lg: 4, md: 4, sm: 4, xs: 4, xxs: 4 }}
|
cols={{ lg: 4, md: 4, sm: 4, xs: 4, xxs: 4 }}
|
||||||
draggableHandle=".drag-widget-icon"
|
draggableHandle=".drag-widget-icon"
|
||||||
isResizable={false}
|
isResizable={false}
|
||||||
margin={[LANDING_PAGE_WIDGET_MARGIN, LANDING_PAGE_WIDGET_MARGIN]}
|
margin={[
|
||||||
|
customizePageClassBase.landingPageWidgetMargin,
|
||||||
|
customizePageClassBase.landingPageWidgetMargin,
|
||||||
|
]}
|
||||||
rowHeight={100}>
|
rowHeight={100}>
|
||||||
{widgets}
|
{widgets}
|
||||||
</ResponsiveGridLayout>
|
</ResponsiveGridLayout>
|
||||||
|
|||||||
@ -273,6 +273,9 @@
|
|||||||
.h-full {
|
.h-full {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
.h-max-full {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
.h-auto {
|
.h-auto {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
@ -284,3 +287,11 @@
|
|||||||
.max-width-md {
|
.max-width-md {
|
||||||
max-width: 768px;
|
max-width: 768px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-y-scroll {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflow-x-scroll {
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|||||||
@ -21,30 +21,26 @@ import {
|
|||||||
uniqueId,
|
uniqueId,
|
||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
import { Layout } from 'react-grid-layout';
|
import { Layout } from 'react-grid-layout';
|
||||||
import {
|
|
||||||
DEFAULT_WIDGET_HEIGHT,
|
|
||||||
LANDING_PAGE_RIGHT_CONTAINER_EDIT_HEIGHT,
|
|
||||||
LANDING_PAGE_ROW_HEIGHT,
|
|
||||||
LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS,
|
|
||||||
LANDING_PAGE_WIDGET_MARGIN,
|
|
||||||
} from '../constants/CustomizePage.constants';
|
|
||||||
import {
|
import {
|
||||||
LandingPageWidgetKeys,
|
LandingPageWidgetKeys,
|
||||||
WidgetWidths,
|
WidgetWidths,
|
||||||
} from '../enums/CustomizablePage.enum';
|
} from '../enums/CustomizablePage.enum';
|
||||||
import { Document } from '../generated/entity/docStore/document';
|
import { Document } from '../generated/entity/docStore/document';
|
||||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||||
|
import customizePageClassBase from './CustomizePageClassBase';
|
||||||
|
|
||||||
export const getAddWidgetHandler =
|
export const getAddWidgetHandler =
|
||||||
(
|
(
|
||||||
newWidgetData: Document,
|
newWidgetData: Document,
|
||||||
placeholderWidgetKey: string,
|
placeholderWidgetKey: string,
|
||||||
|
widgetWidth: number,
|
||||||
maxGridSize: number
|
maxGridSize: number
|
||||||
) =>
|
) =>
|
||||||
(currentLayout: Array<WidgetConfig>) => {
|
(currentLayout: Array<WidgetConfig>) => {
|
||||||
const widgetFQN = uniqueId(`${newWidgetData.fullyQualifiedName}-`);
|
const widgetFQN = uniqueId(`${newWidgetData.fullyQualifiedName}-`);
|
||||||
const widgetWidth = getWidgetWidth(newWidgetData);
|
const widgetHeight = customizePageClassBase.getWidgetHeight(
|
||||||
const widgetHeight = getWidgetHeight(newWidgetData.name);
|
newWidgetData.name
|
||||||
|
);
|
||||||
|
|
||||||
// The widget with key "ExtraWidget.EmptyWidgetPlaceholder" will always remain in the bottom
|
// The widget with key "ExtraWidget.EmptyWidgetPlaceholder" will always remain in the bottom
|
||||||
// and is not meant to be replaced hence
|
// and is not meant to be replaced hence
|
||||||
@ -142,29 +138,6 @@ export const getWidgetWidth = (widget: Document) => {
|
|||||||
return widgetSize as number;
|
return widgetSize as number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWidgetHeight = (widgetName: string) => {
|
|
||||||
switch (widgetName) {
|
|
||||||
case 'ActivityFeed':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.activityFeed;
|
|
||||||
case 'RightSidebar':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.rightSidebar;
|
|
||||||
case 'Announcements':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.announcements;
|
|
||||||
case 'Following':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.following;
|
|
||||||
case 'RecentlyViewed':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.recentlyViewed;
|
|
||||||
case 'MyData':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.myData;
|
|
||||||
case 'KPI':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.kpi;
|
|
||||||
case 'TotalDataAssets':
|
|
||||||
return LANDING_PAGE_WIDGET_DEFAULT_HEIGHTS.totalDataAssets;
|
|
||||||
default:
|
|
||||||
return DEFAULT_WIDGET_HEIGHT;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAllWidgetsArray = (layout: WidgetConfig[]) => {
|
const getAllWidgetsArray = (layout: WidgetConfig[]) => {
|
||||||
const widgetsArray: WidgetConfig[] = [];
|
const widgetsArray: WidgetConfig[] = [];
|
||||||
|
|
||||||
@ -191,13 +164,15 @@ const getLayoutWithCalculatedRightPanelHeight = (
|
|||||||
const floorHeightAndPosValue = floor(widgetHeightAndPos);
|
const floorHeightAndPosValue = floor(widgetHeightAndPos);
|
||||||
|
|
||||||
const heightOfWidget =
|
const heightOfWidget =
|
||||||
widgetHeightAndPos * LANDING_PAGE_ROW_HEIGHT +
|
widgetHeightAndPos * customizePageClassBase.landingPageRowHeight +
|
||||||
(floorHeightAndPosValue + 1) * LANDING_PAGE_WIDGET_MARGIN;
|
(floorHeightAndPosValue + 1) *
|
||||||
|
customizePageClassBase.landingPageWidgetMargin;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
h: round(
|
h: round(
|
||||||
(heightOfWidget + LANDING_PAGE_WIDGET_MARGIN) /
|
(heightOfWidget + customizePageClassBase.landingPageWidgetMargin) /
|
||||||
(LANDING_PAGE_ROW_HEIGHT + LANDING_PAGE_WIDGET_MARGIN),
|
(customizePageClassBase.landingPageRowHeight +
|
||||||
|
customizePageClassBase.landingPageWidgetMargin),
|
||||||
2
|
2
|
||||||
),
|
),
|
||||||
height: heightOfWidget,
|
height: heightOfWidget,
|
||||||
@ -211,7 +186,7 @@ const getLayoutWithCalculatedRightPanelHeight = (
|
|||||||
? {
|
? {
|
||||||
...widget,
|
...widget,
|
||||||
h: increaseHeight
|
h: increaseHeight
|
||||||
? LANDING_PAGE_RIGHT_CONTAINER_EDIT_HEIGHT
|
? customizePageClassBase.landingPageRightContainerEditHeight
|
||||||
: maxHeight?.h ?? widget.h,
|
: maxHeight?.h ?? widget.h,
|
||||||
}
|
}
|
||||||
: widget
|
: widget
|
||||||
|
|||||||
@ -30,10 +30,121 @@ import FollowingWidget, {
|
|||||||
import RecentlyViewed from '../components/recently-viewed/RecentlyViewed';
|
import RecentlyViewed from '../components/recently-viewed/RecentlyViewed';
|
||||||
import TotalDataAssetsWidget from '../components/TotalDataAssetsWidget/TotalDataAssetsWidget.component';
|
import TotalDataAssetsWidget from '../components/TotalDataAssetsWidget/TotalDataAssetsWidget.component';
|
||||||
import FeedsWidget from '../components/Widgets/FeedsWidget/FeedsWidget.component';
|
import FeedsWidget from '../components/Widgets/FeedsWidget/FeedsWidget.component';
|
||||||
import { LandingPageWidgetKeys } from '../enums/CustomizablePage.enum';
|
import {
|
||||||
import { WidgetCommonProps } from '../pages/CustomizablePage/CustomizablePage.interface';
|
LandingPageWidgetKeys,
|
||||||
|
WidgetWidths,
|
||||||
|
} from '../enums/CustomizablePage.enum';
|
||||||
|
import {
|
||||||
|
WidgetCommonProps,
|
||||||
|
WidgetConfig,
|
||||||
|
} from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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> = [
|
||||||
|
{
|
||||||
|
h: this.landingPageWidgetDefaultHeights.activityFeed,
|
||||||
|
i: LandingPageWidgetKeys.ACTIVITY_FEED,
|
||||||
|
w: 3,
|
||||||
|
x: 0,
|
||||||
|
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,
|
||||||
|
w: 1,
|
||||||
|
x: 0,
|
||||||
|
y: 6,
|
||||||
|
static: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
h: this.landingPageWidgetDefaultHeights.kpi,
|
||||||
|
i: LandingPageWidgetKeys.KPI,
|
||||||
|
w: 2,
|
||||||
|
x: 1,
|
||||||
|
y: 6,
|
||||||
|
static: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
h: this.landingPageWidgetDefaultHeights.totalAssets,
|
||||||
|
i: LandingPageWidgetKeys.TOTAL_DATA_ASSETS,
|
||||||
|
w: 3,
|
||||||
|
x: 0,
|
||||||
|
y: 9.1,
|
||||||
|
static: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
protected updateRightPanelDefaultLayout(layout: Array<WidgetConfig>) {
|
||||||
|
this.rightPanelDefaultLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateLandingPageDefaultLayout(layout: Array<WidgetConfig>) {
|
||||||
|
this.landingPageDefaultLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateLandingPageWidgetDefaultHeights(obj: Record<string, number>) {
|
||||||
|
this.landingPageWidgetDefaultHeights = obj;
|
||||||
|
}
|
||||||
|
|
||||||
export class CustomizePageClassBase {
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param string widgetKey
|
* @param string widgetKey
|
||||||
@ -49,11 +160,9 @@ export class CustomizePageClassBase {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
*/
|
*/
|
||||||
static getWidgetsFromKey = (
|
public getWidgetsFromKey(
|
||||||
widgetKey: string
|
widgetKey: string
|
||||||
): FC<
|
): FC<WidgetCommonProps & AnnouncementsWidgetProps & FollowingWidgetProps> {
|
||||||
WidgetCommonProps & AnnouncementsWidgetProps & FollowingWidgetProps
|
|
||||||
> => {
|
|
||||||
if (widgetKey.startsWith(LandingPageWidgetKeys.ACTIVITY_FEED)) {
|
if (widgetKey.startsWith(LandingPageWidgetKeys.ACTIVITY_FEED)) {
|
||||||
return FeedsWidget;
|
return FeedsWidget;
|
||||||
}
|
}
|
||||||
@ -77,9 +186,9 @@ export class CustomizePageClassBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (() => null) as React.FC;
|
return (() => null) as React.FC;
|
||||||
};
|
}
|
||||||
|
|
||||||
static getWidgetImageFromKey = (widgetKey: string): string => {
|
public getWidgetImageFromKey(widgetKey: string, size?: number): string {
|
||||||
switch (widgetKey) {
|
switch (widgetKey) {
|
||||||
case LandingPageWidgetKeys.ACTIVITY_FEED: {
|
case LandingPageWidgetKeys.ACTIVITY_FEED: {
|
||||||
return ActivityFeedImg;
|
return ActivityFeedImg;
|
||||||
@ -88,9 +197,17 @@ export class CustomizePageClassBase {
|
|||||||
return MyDataImg;
|
return MyDataImg;
|
||||||
}
|
}
|
||||||
case LandingPageWidgetKeys.KPI: {
|
case LandingPageWidgetKeys.KPI: {
|
||||||
|
if (size === WidgetWidths.small) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
return KPIImg;
|
return KPIImg;
|
||||||
}
|
}
|
||||||
case LandingPageWidgetKeys.TOTAL_DATA_ASSETS: {
|
case LandingPageWidgetKeys.TOTAL_DATA_ASSETS: {
|
||||||
|
if (size === WidgetWidths.medium) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
return TotalAssetsImg;
|
return TotalAssetsImg;
|
||||||
}
|
}
|
||||||
case LandingPageWidgetKeys.ANNOUNCEMENTS: {
|
case LandingPageWidgetKeys.ANNOUNCEMENTS: {
|
||||||
@ -106,5 +223,33 @@ export class CustomizePageClassBase {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
public getWidgetHeight(widgetName: string) {
|
||||||
|
switch (widgetName) {
|
||||||
|
case 'ActivityFeed':
|
||||||
|
return this.landingPageWidgetDefaultHeights.activityFeed;
|
||||||
|
case 'RightSidebar':
|
||||||
|
return this.landingPageWidgetDefaultHeights.rightSidebar;
|
||||||
|
case 'Announcements':
|
||||||
|
return this.landingPageWidgetDefaultHeights.announcements;
|
||||||
|
case 'Following':
|
||||||
|
return this.landingPageWidgetDefaultHeights.following;
|
||||||
|
case 'RecentlyViewed':
|
||||||
|
return this.landingPageWidgetDefaultHeights.recentlyViewed;
|
||||||
|
case 'MyData':
|
||||||
|
return this.landingPageWidgetDefaultHeights.myData;
|
||||||
|
case 'KPI':
|
||||||
|
return this.landingPageWidgetDefaultHeights.kpi;
|
||||||
|
case 'TotalAssets':
|
||||||
|
return this.landingPageWidgetDefaultHeights.totalAssets;
|
||||||
|
default:
|
||||||
|
return this.defaultWidgetHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customizePageClassBase = new CustomizePageClassBase();
|
||||||
|
|
||||||
|
export default customizePageClassBase;
|
||||||
|
export { CustomizePageClassBase };
|
||||||
|
|||||||
@ -328,18 +328,18 @@ export const getGlobalSettingsMenuWithPermission = (
|
|||||||
category: i18next.t('label.open-metadata'),
|
category: i18next.t('label.open-metadata'),
|
||||||
key: 'openMetadata',
|
key: 'openMetadata',
|
||||||
items: [
|
items: [
|
||||||
{
|
|
||||||
label: i18next.t('label.email'),
|
|
||||||
isProtected: Boolean(isAdminUser),
|
|
||||||
key: 'openMetadata.email',
|
|
||||||
icon: <EmailSettingsIcon className="w-4 side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: i18next.t('label.customize-landing-page'),
|
label: i18next.t('label.customize-landing-page'),
|
||||||
isProtected: Boolean(isAdminUser),
|
isProtected: Boolean(isAdminUser),
|
||||||
key: 'openMetadata.customizeLandingPage',
|
key: 'openMetadata.customizeLandingPage',
|
||||||
icon: <CustomDashboardLogoIcon className="w-4 side-panel-icons" />,
|
icon: <CustomDashboardLogoIcon className="w-4 side-panel-icons" />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: i18next.t('label.email'),
|
||||||
|
isProtected: Boolean(isAdminUser),
|
||||||
|
key: 'openMetadata.email',
|
||||||
|
icon: <EmailSettingsIcon className="w-4 side-panel-icons" />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: i18next.t('label.custom-logo'),
|
label: i18next.t('label.custom-logo'),
|
||||||
isProtected: Boolean(isAdminUser),
|
isProtected: Boolean(isAdminUser),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user