Skip to content

Commit ba99766

Browse files
authored
CardView: Fix the load panel overlapping the whole page (DevExpress#31005)
Co-authored-by: Alyar <>
1 parent 81ff037 commit ba99766

File tree

14 files changed

+172
-8
lines changed

14 files changed

+172
-8
lines changed
9.04 KB
Loading
8.35 KB
Loading
10.4 KB
Loading
12.2 KB
Loading
11.5 KB
Loading
14.1 KB
Loading
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import CardView from 'devextreme-testcafe-models/cardView';
2+
import { createScreenshotsComparer } from 'devextreme-screenshot-comparer';
3+
import { testScreenshot } from '../../helpers/themeUtils';
4+
import url from '../../helpers/getPageUrl';
5+
import { createWidget } from '../../helpers/createWidget';
6+
import { safeSizeTest } from '../../helpers/safeSizeTest';
7+
8+
fixture.disablePageReloads`CardView - LoadPanel`
9+
.page(url(__dirname, '../container.html'));
10+
11+
const CARD_VIEW_SELECTOR = '#container';
12+
13+
safeSizeTest('Default render', async (t) => {
14+
const cardView = new CardView(CARD_VIEW_SELECTOR);
15+
const { takeScreenshot, compareResults } = createScreenshotsComparer(t);
16+
17+
await testScreenshot(t, takeScreenshot, 'load-panel.png', { element: cardView.element });
18+
19+
await t
20+
.expect(compareResults.isValid())
21+
.ok(compareResults.errorMessages());
22+
}, [800, 800]).before(async () => createWidget('dxCardView', {
23+
width: 500,
24+
height: 300,
25+
dataSource: {
26+
key: 'id',
27+
load: () => new Promise(() => {}),
28+
},
29+
columns: ['A', 'B', 'C', 'D'],
30+
}));
31+
32+
safeSizeTest('Default render when CardView has a large height', async (t) => {
33+
const { takeScreenshot, compareResults } = createScreenshotsComparer(t);
34+
35+
await testScreenshot(t, takeScreenshot, 'load-panel-with-large-height.png');
36+
37+
await t
38+
.expect(compareResults.isValid())
39+
.ok(compareResults.errorMessages());
40+
}, [800, 800]).before(async () => createWidget('dxCardView', {
41+
width: 500,
42+
height: 3000,
43+
dataSource: {
44+
key: 'id',
45+
load: () => new Promise(() => {}),
46+
},
47+
columns: ['A', 'B', 'C', 'D'],
48+
}));
49+
50+
safeSizeTest('The load panel should match the size of the component’s root container', async (t) => {
51+
const cardView = new CardView(CARD_VIEW_SELECTOR);
52+
const loadPanel = cardView.getLoadPanel();
53+
const cardViewOffset = await cardView.getElementOffset();
54+
55+
await t
56+
.expect(loadPanel.getShadowWidth())
57+
.eql(500)
58+
.expect(loadPanel.getShadowHeight())
59+
.eql(300)
60+
.expect(loadPanel.getShadowOffset())
61+
.eql(cardViewOffset);
62+
}, [800, 800]).before(async () => createWidget('dxCardView', {
63+
width: 500,
64+
height: 300,
65+
dataSource: {
66+
key: 'id',
67+
load: () => new Promise(() => {}),
68+
},
69+
columns: ['A', 'B', 'C', 'D'],
70+
}));

packages/devextreme/js/__internal/grids/new/card_view/main_view.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ToolbarView } from '@ts/grids/new/grid_core/toolbar/view';
1010
import type { ComponentType, RefObject } from 'inferno';
1111

1212
import { A11yStatusContainer, AccessibilityController } from '../grid_core/accessibility/index';
13+
import { CommonPropsContext } from '../grid_core/core/common_props_context';
1314
import type { Config } from '../grid_core/core/config_context';
1415
import { ConfigContext } from '../grid_core/core/config_context';
1516
import { EditPopupView } from '../grid_core/editing/popup/view';
@@ -34,7 +35,9 @@ interface MainViewProps {
3435
EditPopup: ComponentType;
3536
ContextMenu: ComponentType;
3637
config: Config;
37-
rootElementRef: RefObject<HTMLDivElement>;
38+
commonProps: {
39+
rootElementRef: RefObject<HTMLDivElement>;
40+
};
3841
accessibilityDescription: string;
3942
accessibilityStatus: string;
4043
onKeyDown: (event: KeyboardEvent) => void;
@@ -51,15 +54,16 @@ function MainViewComponent({
5154
ContextMenu,
5255
EditPopup,
5356
config,
54-
rootElementRef,
57+
commonProps,
5558
accessibilityDescription,
5659
accessibilityStatus,
5760
onKeyDown,
5861
}: MainViewProps): JSX.Element {
5962
return (<>
6063
<ConfigContext.Provider value={config}>
64+
<CommonPropsContext.Provider value={commonProps}>
6165
<RootElementUpdater
62-
rootElementRef={rootElementRef}
66+
rootElementRef={commonProps.rootElementRef}
6367
className={CLASSES.cardView}
6468
>
6569
<div
@@ -91,6 +95,7 @@ function MainViewComponent({
9195
<ContextMenu/>
9296
</div>
9397
</RootElementUpdater>
98+
</CommonPropsContext.Provider>
9499
</ConfigContext.Provider>
95100
</>);
96101
}
@@ -104,6 +109,10 @@ export class MainView extends View<MainViewProps> {
104109
templatesRenderAsynchronously: this.options.oneWay('templatesRenderAsynchronously').value,
105110
}));
106111

112+
private readonly commonProps = {
113+
rootElementRef: { current: this.root! },
114+
};
115+
107116
public static dependencies = [
108117
ContentView,
109118
PagerView,
@@ -139,6 +148,8 @@ export class MainView extends View<MainViewProps> {
139148
// eslint-disable-next-line @stylistic/max-len
140149
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type
141150
protected override getProps() {
151+
this.commonProps.rootElementRef.current = this.root!;
152+
142153
return computed(() => ({
143154
Toolbar: this.toolbar.asInferno(),
144155
Content: this.content.asInferno(),
@@ -150,7 +161,7 @@ export class MainView extends View<MainViewProps> {
150161
EditPopup: this.editPopup.asInferno(),
151162
ContextMenu: this.contextMenu.asInferno(),
152163
config: this.config.value,
153-
rootElementRef: { current: this.root! },
164+
commonProps: this.commonProps,
154165
onKeyDown: (event: KeyboardEvent): void => {
155166
this.keyboardNavigation.onKeyDown(event);
156167
},

packages/devextreme/js/__internal/grids/new/grid_core/content_view/content_view.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import type { ErrorRowProperties } from '@ts/grids/new/grid_core/content_view/er
55
import { ErrorRow } from '@ts/grids/new/grid_core/content_view/error_row';
66
import type { NoDataTextProperties } from '@ts/grids/new/grid_core/content_view/no_data_text';
77
import { NoDataText } from '@ts/grids/new/grid_core/content_view/no_data_text';
8-
import { LoadPanel, type LoadPanelProperties } from '@ts/grids/new/grid_core/inferno_wrappers/load_panel';
98
import type { Props as ScrollableProps } from '@ts/grids/new/grid_core/inferno_wrappers/scrollable';
109
import { Scrollable } from '@ts/grids/new/grid_core/inferno_wrappers/scrollable';
1110
import type { RefObject } from 'inferno';
1211
import { Component, createRef } from 'inferno';
1312

13+
import { LoadPanel, type LoadPanelProperties } from './load_panel';
14+
1415
export const CLASSES = {
1516
contentView: 'dx-gridcore-contentview',
1617
};
Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,36 @@
1-
export { LoadPanel } from '../inferno_wrappers/load_panel';
1+
import type { PositionConfig } from '@js/common/core/animation';
2+
import { getWindow } from '@js/core/utils/window';
3+
import { BaseInfernoComponent } from '@ts/core/r1/runtime/inferno/index';
4+
5+
import { CommonPropsContext } from '../core/common_props_context';
6+
import type { LoadPanelProperties } from '../inferno_wrappers/load_panel';
7+
import { LoadPanel as LoadPanelBase } from '../inferno_wrappers/load_panel';
8+
9+
export { LoadPanelProperties };
10+
11+
export class LoadPanel extends BaseInfernoComponent<LoadPanelProperties> {
12+
private calculatePosition(rootElement: HTMLElement): PositionConfig {
13+
const window = getWindow();
14+
15+
if (rootElement.offsetHeight > window.innerHeight) {
16+
return {
17+
of: window,
18+
boundary: rootElement,
19+
collision: 'fit',
20+
};
21+
}
22+
return { of: rootElement };
23+
}
24+
25+
public render(): JSX.Element {
26+
const { rootElementRef } = this.context[CommonPropsContext.id];
27+
28+
const loadPanelProperties: LoadPanelProperties = {
29+
container: rootElementRef.current,
30+
position: this.calculatePosition(rootElementRef.current),
31+
...this.props,
32+
};
33+
34+
return <LoadPanelBase {...loadPanelProperties} />;
35+
}
36+
}

0 commit comments

Comments
 (0)