diff --git a/src/ui/registry/units/dash/components-map.tsx b/src/ui/registry/units/dash/components-map.tsx index ac4a42c2eb..f0df2ce37a 100644 --- a/src/ui/registry/units/dash/components-map.tsx +++ b/src/ui/registry/units/dash/components-map.tsx @@ -1,3 +1,5 @@ +import type {Props as DashBodyContentProps} from 'ui/units/dash/containers/Body/components/Content/Content'; + import type {DialogTextWidgetProps} from '../../../components/DialogTextWidget/DialogTextWidget'; import {makeDefaultEmpty} from '../../components/DefaultEmpty'; @@ -8,6 +10,7 @@ export const dashComponentsMap = { DashSelectState: makeDefaultEmpty(), DashSelectStateDialog: makeDefaultEmpty(), DialogTextWidget: makeDefaultEmpty(), + DashBodyContent: makeDefaultEmpty(), DashBodyAdditionalControls: makeDefaultEmpty(), DialogDashOtherSettingsPrepend: makeDefaultEmpty(), DashActionPanelAdditionalButtons: makeDefaultEmpty(), diff --git a/src/ui/registry/units/dash/register.tsx b/src/ui/registry/units/dash/register.tsx index 8e87e827a8..eb4fdef421 100644 --- a/src/ui/registry/units/dash/register.tsx +++ b/src/ui/registry/units/dash/register.tsx @@ -3,6 +3,7 @@ import {EXAMPLE_FUNCTION} from 'ui/registry/units/common/constants/functions'; import {getMinAutoupdateInterval} from 'ui/units/dash/containers/Dialogs/Settings/utils'; import DialogTextWidget from '../../../components/DialogTextWidget/DialogTextWidget'; +import {LazyContent} from '../../../units/dash/containers/Body/components/Content/LazyContent'; import {getCaptionText} from '../../../units/dash/containers/Dialogs/Tabs/PopupWidgetsOrder/helpers'; import {getExtendedItemData} from '../../../units/dash/store/actions/helpers'; import {getDashEntryUrl, getNewDashUrl} from '../../../units/dash/utils/url'; @@ -10,6 +11,7 @@ import {registry} from '../../index'; export const registerDashPlugins = () => { registry.dash.components.registerMany({ + DashBodyContent: LazyContent, DialogTextWidget, }); diff --git a/src/ui/units/dash/containers/Body/Body.tsx b/src/ui/units/dash/containers/Body/Body.tsx index d6d1dac2d4..5c184a4005 100644 --- a/src/ui/units/dash/containers/Body/Body.tsx +++ b/src/ui/units/dash/containers/Body/Body.tsx @@ -11,11 +11,7 @@ import type { PreparedCopyItemOptions, ReactGridLayoutProps, } from '@gravity-ui/dashkit'; -import { - DashKitDnDWrapper, - ActionPanel as DashkitActionPanel, - DashKit as GravityDashkit, -} from '@gravity-ui/dashkit'; +import {DashKit as GravityDashkit} from '@gravity-ui/dashkit'; import {DEFAULT_GROUP, MenuItems} from '@gravity-ui/dashkit/helpers'; import { ChevronsDown, @@ -46,15 +42,11 @@ import type {DashTab, DashTabItem, DashTabLayout} from 'shared'; import { ControlQA, DASH_INFO_HEADER, - DashBodyQa, - DashEntryQa, DashKitOverlayMenuQa, DashTabItemType, - EntryScope, FOCUSED_WIDGET_PARAM_NAME, Feature, FixedHeaderQa, - LOADED_DASH_CLASS, SCROLL_TITLE_DEBOUNCE_TIME, UPDATE_STATE_DEBOUNCE_TIME, } from 'shared'; @@ -68,18 +60,13 @@ import {WidgetContextProvider} from 'ui/components/DashKit/context/WidgetContext import {getDashKitMenu} from 'ui/components/DashKit/helpers'; import {registry} from 'ui/registry'; import {showToast} from 'ui/store/actions/toaster'; -import {selectAsideHeaderIsCompact} from 'ui/store/selectors/asideHeader'; -import {selectUserSettings} from 'ui/store/selectors/user'; import {isEmbeddedMode} from 'ui/utils/embedded'; import {isEnabledFeature} from 'ui/utils/isEnabledFeature'; -import {getIsAsideHeaderEnabled} from '../../../../components/AsideHeaderAdapter'; import {getConfiguredDashKit} from '../../../../components/DashKit/DashKit'; import {DL} from '../../../../constants'; -import Utils from '../../../../utils'; -import {TYPES_TO_DIALOGS_MAP, getActionPanelItems} from '../../../../utils/getActionPanelItems'; +import {TYPES_TO_DIALOGS_MAP} from '../../../../utils/getActionPanelItems'; import {EmptyState} from '../../components/EmptyState/EmptyState'; -import Loader from '../../components/Loader/Loader'; import {Mode} from '../../modules/constants'; import type {CopiedConfigContext, CopiedConfigData} from '../../modules/helpers'; import { @@ -88,7 +75,6 @@ import { getLayoutParentId, getPastedWidgetData, getPreparedCopyItemOptions, - memoizedGetLocalTabs, } from '../../modules/helpers'; import type {TabsHashStates} from '../../store/actions/dashTyped'; import { @@ -108,28 +94,24 @@ import { selectCurrentTab, selectCurrentTabId, selectDashDescription, - selectDashError, selectDashShowOpenedDescription, selectDashWorkbookId, selectEntryId, selectLastModifiedItemId, selectSettings, - selectShowTableOfContent, selectSkipReload, selectTabHashState, selectTabs, } from '../../store/selectors/dashTypedSelectors'; import {getCustomizedProperties} from '../../utils/dashkitProps'; import {scrollIntoView} from '../../utils/scrollUtils'; -import {DashError} from '../DashError/DashError'; import { FixedHeaderContainer, FixedHeaderControls, FixedHeaderWrapper, } from '../FixedHeader/FixedHeader'; -import TableOfContent from '../TableOfContent/TableOfContent'; -import {Tabs} from '../Tabs/Tabs'; +import Content from './components/Content/Content'; import { FixedContainerWrapperWithContext, FixedControlsWrapperWithContext, @@ -426,7 +408,24 @@ class Body extends React.PureComponent { return (
- {this.renderBody()} + @@ -1304,104 +1303,6 @@ class Body extends React.PureComponent { }); } }; - - private renderBody() { - const { - mode, - settings, - tabs, - showTableOfContent, - isSidebarOpened, - hideErrorDetails, - onRetry, - error, - disableHashNavigation, - } = this.props; - - const {loaded, hasCopyInBuffer} = this.state; - - switch (mode) { - case Mode.Loading: - case Mode.Updating: - return ; - case Mode.Error: - return ; - } - - const localTabs = memoizedGetLocalTabs(tabs); - - const hasTableOfContentForTab = !(localTabs.length === 1 && !localTabs[0].items.length); - - const showEditActionPanel = this.isEditMode(); - - const loadedMixin = loaded ? LOADED_DASH_CLASS : undefined; - - const hideDashTitle = - settings.hideDashTitle || (DL.IS_MOBILE && !isMobileFixedHeaderEnabled); - - const content = ( -
-
1, - })} - > - -
- {!hideDashTitle && this.props.entry?.key && ( -
- {Utils.getEntryNameFromKey(this.props.entry?.key)} -
- )} - {!settings.hideTabs && } - {this.renderDashkit()} - {!this.props.onlyView && ( - item.id === DashTabItemType.Image, - userSettings: this.props.userSettings, - scope: EntryScope.Dash, - })} - className={b('edit-panel', { - 'aside-opened': isSidebarOpened, - })} - /> - )} -
-
-
- ); - - return ( - - {content} - - ); - } } const mapStateToProps = (state: DatalensGlobalState) => ({ @@ -1409,7 +1310,6 @@ const mapStateToProps = (state: DatalensGlobalState) => ({ lastModifiedItem: selectLastModifiedItemId(state), entry: state.dash.entry, mode: state.dash.mode, - showTableOfContent: selectShowTableOfContent(state), hashStates: selectTabHashState(state), settings: selectSettings(state), tabData: selectCurrentTab(state), @@ -1417,11 +1317,8 @@ const mapStateToProps = (state: DatalensGlobalState) => ({ canEdit: canEdit(state), tabs: selectTabs(state), tabId: selectCurrentTabId(state), - isSidebarOpened: !selectAsideHeaderIsCompact(state), workbookId: selectDashWorkbookId(state), - error: selectDashError(state), skipReload: selectSkipReload(state), - userSettings: selectUserSettings(state), dashDescription: selectDashDescription(state), showOpenedDescription: selectDashShowOpenedDescription(state), hasTableOfContent: hasTableOfContent(state), diff --git a/src/ui/units/dash/containers/Body/components/Content/Content.tsx b/src/ui/units/dash/containers/Body/components/Content/Content.tsx new file mode 100644 index 0000000000..5808804861 --- /dev/null +++ b/src/ui/units/dash/containers/Body/components/Content/Content.tsx @@ -0,0 +1,172 @@ +import React from 'react'; + +import type {ConfigLayout} from '@gravity-ui/dashkit'; +import {DashKitDnDWrapper, ActionPanel as DashkitActionPanel} from '@gravity-ui/dashkit'; +import block from 'bem-cn-lite'; +import {useDispatch, useSelector} from 'react-redux'; +import { + DashBodyQa, + DashEntryQa, + DashTabItemType, + EntryScope, + Feature, + LOADED_DASH_CLASS, +} from 'shared'; +import {selectAsideHeaderIsCompact} from 'ui/store/selectors/asideHeader'; +import {selectUserSettings} from 'ui/store/selectors/user'; +import {isEnabledFeature} from 'ui/utils/isEnabledFeature'; + +import {getIsAsideHeaderEnabled} from '../../../../../../components/AsideHeaderAdapter'; +import {DL} from '../../../../../../constants'; +import Utils from '../../../../../../utils'; +import {getActionPanelItems} from '../../../../../../utils/getActionPanelItems'; +import Loader from '../../../../components/Loader/Loader'; +import {Mode} from '../../../../modules/constants'; +import type {CopiedConfigData} from '../../../../modules/helpers'; +import {memoizedGetLocalTabs} from '../../../../modules/helpers'; +import {openDialog} from '../../../../store/actions/dialogs/actions'; +import { + selectDashError, + selectSettings, + selectShowTableOfContent, + selectTabs, +} from '../../../../store/selectors/dashTypedSelectors'; +import {DashError} from '../../../DashError/DashError'; +import TableOfContent from '../../../TableOfContent/TableOfContent'; +import {Tabs} from '../../../Tabs/Tabs'; + +const b = block('dash-body'); + +const isMobileFixedHeaderEnabled = isEnabledFeature(Feature.EnableMobileFixedHeader); + +export type Props = { + copiedData: CopiedConfigData | null; + dashEntryKey?: string; + disableHashNavigation?: boolean; + hideErrorDetails?: boolean; + isCondensed: boolean; + loaded: boolean; + mode: Mode; + showEditActionPanel: boolean; + renderDashkit: () => void; + onDragEnd: () => void; + onDragStart: () => void; + onItemClick: (itemTitle: string) => void; + onRetry: () => void; +} & ( + | {onlyView: true} + | { + onlyView?: boolean; + onPasteItem: (data: CopiedConfigData, newLayout?: ConfigLayout[]) => void; + } +); + +const Content = ({ + copiedData, + dashEntryKey, + disableHashNavigation, + hideErrorDetails, + isCondensed, + loaded, + mode, + showEditActionPanel, + renderDashkit, + onDragEnd, + onDragStart, + onItemClick, + onRetry, + ...restProps +}: Props) => { + const dispatch = useDispatch(); + + const error = useSelector(selectDashError); + const isSidebarOpened = !useSelector(selectAsideHeaderIsCompact); + const settings = useSelector(selectSettings); + const showTableOfContent = useSelector(selectShowTableOfContent); + const tabs = useSelector(selectTabs); + const userSettings = useSelector(selectUserSettings); + + const handleOpenDialog = React.useCallback<(...args: Parameters) => void>( + (dialogType, dragOperationProps) => { + dispatch(openDialog(dialogType, dragOperationProps)); + }, + [dispatch], + ); + + switch (mode) { + case Mode.Loading: + case Mode.Updating: + return ; + case Mode.Error: + return ; + } + + const localTabs = memoizedGetLocalTabs(tabs); + + const hasTableOfContentForTab = !(localTabs.length === 1 && !localTabs[0].items.length); + + const loadedMixin = loaded ? LOADED_DASH_CLASS : undefined; + + const hideDashTitle = settings.hideDashTitle || (DL.IS_MOBILE && !isMobileFixedHeaderEnabled); + + return ( + +
+
1, + })} + > + +
+ {!hideDashTitle && dashEntryKey && ( +
+ {Utils.getEntryNameFromKey(dashEntryKey)} +
+ )} + {!settings.hideTabs && } + {renderDashkit()} + {!restProps.onlyView && ( + item.id === DashTabItemType.Image, + userSettings, + scope: EntryScope.Dash, + })} + className={b('edit-panel', { + 'aside-opened': isSidebarOpened, + })} + /> + )} +
+
+
+
+ ); +}; + +export default Content; diff --git a/src/ui/units/dash/containers/Body/components/Content/LazyContent.tsx b/src/ui/units/dash/containers/Body/components/Content/LazyContent.tsx new file mode 100644 index 0000000000..e1380d2f9b --- /dev/null +++ b/src/ui/units/dash/containers/Body/components/Content/LazyContent.tsx @@ -0,0 +1,3 @@ +import React from 'react'; + +export const LazyContent = React.lazy(() => import('./Content'));