Skip to content

Commit 7acbd2a

Browse files
authored
Merge pull request #2379 from tf/img-collapse
Fix inline image collapse when file is not ready
2 parents d193d01 + 81924fb commit 7acbd2a

File tree

19 files changed

+174
-39
lines changed

19 files changed

+174
-39
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react';
2+
3+
import {ExternalLinkList} from 'contentElements/externalLinkList/frontend/ExternalLinkList';
4+
5+
import {renderInContentElement} from 'pageflow-scrolled/testHelpers';
6+
import '@testing-library/jest-dom/extend-expect'
7+
8+
import styles from 'frontend/Placeholder.module.css';
9+
10+
describe('ExternalLinkList placeholder', () => {
11+
it('renders placeholder in editor', () => {
12+
const {container} = renderInContentElement(
13+
<ExternalLinkList configuration={{links: [{id: 1}]}}
14+
sectionProps={{}} />,
15+
{editorState: {isEditable: true}}
16+
);
17+
18+
expect(container.querySelector(`.${styles.placeholder}`)).not.toBeNull();
19+
});
20+
21+
it('does not render placeholder in published entry', () => {
22+
const {container} = renderInContentElement(
23+
<ExternalLinkList configuration={{links: [{id: 1}]}}
24+
sectionProps={{}} />,
25+
{editorState: {isEditable: false}}
26+
);
27+
28+
expect(container.querySelector(`.${styles.placeholder}`)).toBeNull();
29+
});
30+
});

entry_types/scrolled/package/spec/contentElements/inlineImage/InlineImage-spec.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,5 +337,23 @@ describe('InlineImage', () => {
337337
const contentElement = getContentElement();
338338
expect(contentElement.getFitViewportAspectRatio()).toEqual('0.75');
339339
});
340+
341+
it('uses default aspect ratio when file is not ready', () => {
342+
const {getContentElement} = renderContentElement({
343+
typeName: 'inlineImage',
344+
configuration: {
345+
id: 100
346+
},
347+
imageFiles: [{
348+
permaId: 100,
349+
isReady: false,
350+
width: null,
351+
height: null
352+
}]
353+
});
354+
355+
const contentElement = getContentElement();
356+
expect(contentElement.getFitViewportAspectRatio()).toEqual('0.75');
357+
});
340358
});
341359
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
import {render} from '@testing-library/react';
3+
import '@testing-library/jest-dom/extend-expect';
4+
5+
import {FilePlaceholder} from 'frontend/FilePlaceholderDecorator';
6+
import styles from 'frontend/Placeholder.module.css';
7+
8+
describe('FilePlaceholder', () => {
9+
it('renders placeholder when no file is given', () => {
10+
const {container} = render(
11+
<FilePlaceholder />
12+
);
13+
14+
expect(container.querySelector(`.${styles.placeholder}`)).not.toBeNull();
15+
});
16+
17+
it('renders placeholder when file is not ready', () => {
18+
const {container} = render(
19+
<FilePlaceholder file={{isReady: false}} />
20+
);
21+
22+
expect(container.querySelector(`.${styles.placeholder}`)).not.toBeNull();
23+
});
24+
25+
it('does not render placeholder when file is ready', () => {
26+
const {container} = render(
27+
<FilePlaceholder file={{isReady: true}} />
28+
);
29+
30+
expect(container.querySelector(`.${styles.placeholder}`)).toBeNull();
31+
});
32+
});

entry_types/scrolled/package/spec/frontend/FitViewport-spec.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,35 +61,47 @@ describe('FitViewport', () => {
6161
expect(getOuter(container)).toHaveStyle('--fit-viewport-scale: 0.8');
6262
});
6363

64-
it('is not opaque by default', () => {
64+
it('support covering full height', () => {
6565
const {container} = render(
66-
<FitViewport aspectRatio={0.5}>
66+
<FitViewport aspectRatio={0.5} fill>
6767
<FitViewport.Content />
6868
</FitViewport>
6969
);
7070

71-
expect(getOuter(container)).not.toHaveClass(styles.opaque);
71+
expect(getOuter(container)).not.toHaveStyle('--fit-viewport-aspect-ratio: 0.5');
72+
expect(container.querySelector(`.${fullscreenStyles.root}`)).not.toBeNull();
7273
});
7374

74-
it('can be made opaque', () => {
75+
it('uses fallback aspect ratio when file is present but not ready', () => {
76+
const file = {isReady: false};
7577
const {container} = render(
76-
<FitViewport aspectRatio={0.5} opaque>
78+
<FitViewport file={file} fallbackAspectRatio={0.75}>
7779
<FitViewport.Content />
7880
</FitViewport>
7981
);
8082

81-
expect(getOuter(container)).toHaveClass(styles.opaque);
83+
expect(getOuter(container)).toHaveStyle('--fit-viewport-aspect-ratio: 0.75');
8284
});
8385

84-
it('support covering full height', () => {
86+
it('uses file aspect ratio when file is ready even if fallback is given', () => {
87+
const file = {width: 200, height: 100};
8588
const {container} = render(
86-
<FitViewport aspectRatio={0.5} fill>
89+
<FitViewport file={file} fallbackAspectRatio={0.75}>
8790
<FitViewport.Content />
8891
</FitViewport>
8992
);
9093

91-
expect(getOuter(container)).not.toHaveStyle('--fit-viewport-aspect-ratio: 0.5');
92-
expect(container.querySelector(`.${fullscreenStyles.root}`)).not.toBeNull();
94+
expect(getOuter(container)).toHaveStyle('--fit-viewport-aspect-ratio: 0.5');
95+
});
96+
97+
it('uses fallback aspect ratio when no file is present', () => {
98+
const {container} = render(
99+
<FitViewport fallbackAspectRatio={0.75}>
100+
<FitViewport.Content />
101+
</FitViewport>
102+
);
103+
104+
expect(getOuter(container)).toHaveStyle('--fit-viewport-aspect-ratio: 0.75');
93105
});
94106

95107
function getOuter(container) {

entry_types/scrolled/package/src/contentElements/externalLinkList/frontend/ExternalLink.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ export function ExternalLink({id, configuration, contentElementId, ...props}) {
165165
aspectRatio={props.thumbnailAspectRatio}
166166
cropPosition={props.thumbnailCropPosition}
167167
fit={props.thumbnailFit}
168-
load={props.loadImages}>
168+
load={props.loadImages}
169+
showPlaceholder={isEditable}>
169170
<InlineFileRights configuration={configuration}
170171
context="insideElement"
171172
position={props.textPosition === 'overlay' ? 'top': 'bottom'}

entry_types/scrolled/package/src/contentElements/externalLinkList/frontend/Thumbnail.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React from 'react';
22
import classNames from 'classnames';
33

4-
import {Image} from 'pageflow-scrolled/frontend';
4+
import {Image, FilePlaceholder} from 'pageflow-scrolled/frontend';
55

66
import styles from './Thumbnail.module.css';
77

8-
export function Thumbnail({imageFile, aspectRatio, cropPosition, fit, load, children}) {
8+
export function Thumbnail({imageFile, aspectRatio, cropPosition, fit, load, showPlaceholder, children}) {
99
imageFile = {
1010
...imageFile,
1111
cropPosition
@@ -17,6 +17,7 @@ export function Thumbnail({imageFile, aspectRatio, cropPosition, fit, load, chil
1717
<div className={classNames(styles.thumbnail,
1818
{[styles.cover]: fit === 'cover'})}
1919
style={{paddingTop: aspectRatioPadding}}>
20+
{showPlaceholder && <FilePlaceholder file={imageFile} />}
2021
<Image imageFile={imageFile}
2122
load={load}
2223
preferSvg={true}

entry_types/scrolled/package/src/contentElements/hotspots/Hotspots.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ContentElementBox,
66
Image,
77
ContentElementFigure,
8+
FilePlaceholder,
89
FitViewport,
910
FullscreenViewer,
1011
ToggleFullscreenCornerButton,
@@ -97,7 +98,7 @@ export function HotspotsImage({
9798
const {shouldLoad} = useContentElementLifecycle();
9899
const {isEditable, isSelected} = useContentElementEditorState();
99100

100-
const aspectRatio = imageFile ? `${imageFile.width} / ${imageFile.height}` : '3 / 4';
101+
const aspectRatio = imageFile ? `${imageFile.width} / ${imageFile.height}` : '4 / 3';
101102

102103
const [containerRect, containerRef] = useContentRect({
103104
enabled: shouldLoad
@@ -235,9 +236,8 @@ export function HotspotsImage({
235236
activeIndex={activeIndex}
236237
activateArea={activateArea}>
237238
<FitViewport file={imageFile}
238-
aspectRatio={imageFile ? undefined : 0.75}
239-
fill={configuration.position === 'backdrop'}
240-
opaque={!imageFile}>
239+
fallbackAspectRatio={0.75}
240+
fill={configuration.position === 'backdrop'}>
241241
<Composite activeIndex={activeIndex + 1}
242242
loop={false}
243243
onNavigate={index => activateArea(index - 1)}>
@@ -248,6 +248,7 @@ export function HotspotsImage({
248248
<FitViewport.Content>
249249
<div className={styles.stack}
250250
ref={containerRef}>
251+
<FilePlaceholder file={imageFile} />
251252
{renderLetterboxBackground()}
252253
<div className={styles.wrapper}
253254
ref={panZoomRefs.wrapper}

entry_types/scrolled/package/src/contentElements/iframeEmbed/IframeEmbed.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ContentElementBox,
66
ContentElementFigure,
77
FitViewport,
8+
Placeholder,
89
ThirdPartyOptIn,
910
ThirdPartyOptOutInfo,
1011
useContentElementEditorState,
@@ -55,10 +56,10 @@ export function IframeEmbed({configuration}) {
5556
return (
5657
<div className={styles.wrapper}
5758
style={{pointerEvents: isEditable && !isSelected ? 'none' : undefined}}>
58-
<FitViewport aspectRatio={configuration.autoResize ? null : aspectRatios[aspectRatio || 'wide']}
59-
opaque={utils.isBlank(configuration.source)}>
59+
<FitViewport aspectRatio={configuration.autoResize ? null : aspectRatios[aspectRatio || 'wide']}>
6060
<ContentElementBox>
6161
<ContentElementFigure configuration={configuration}>
62+
{utils.isBlank(configuration.source) && <Placeholder />}
6263
{renderSpanningWrapper(
6364
<ThirdPartyOptIn>
6465
{shouldLoad &&

entry_types/scrolled/package/src/contentElements/imageGallery/ImageGallery.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
useFileWithInlineRights,
88
ContentElementBox,
99
Figure,
10+
FilePlaceholder,
1011
FitViewport,
1112
FullscreenViewer,
1213
Image,
@@ -250,16 +251,16 @@ function ItemImageWithCaption({item, imageFile, configuration, current, onClick,
250251

251252
return (
252253
<FitViewport file={imageFile}
253-
aspectRatio={imageFile ? undefined : 0.75}
254-
scale={0.8}
255-
opaque={!imageFile}>
254+
fallbackAspectRatio={0.75}
255+
scale={0.8}>
256256
<ContentElementBox>
257257
<Figure caption={caption}
258258
variant={configuration.captionVariant}
259259
onCaptionChange={handleCaptionChange}
260260
addCaptionButtonVisible={current && !item.placeholder}
261261
addCaptionButtonPosition="inside">
262262
<FitViewport.Content>
263+
<FilePlaceholder file={imageFile} />
263264
<div onClick={onClick}>
264265
<Image imageFile={imageFile} load={shouldLoad} />
265266
</div>

entry_types/scrolled/package/src/contentElements/inlineImage/InlineImage.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ContentElementBox,
55
Image,
66
ContentElementFigure,
7+
FilePlaceholder,
78
FitViewport,
89
contentElementWidths,
910
useContentElementLifecycle,
@@ -90,8 +91,8 @@ function ImageWithCaption({
9091

9192
return (
9293
<FitViewport file={imageFile}
93-
aspectRatio={aspectRatio || (imageFile ? undefined : 0.75)}
94-
opaque={!imageFile}>
94+
aspectRatio={aspectRatio}
95+
fallbackAspectRatio={0.75}>
9596
<ContentElementBox borderRadius={isCircleCrop ? 'none' : rounded}>
9697
<ContentElementFigure configuration={configuration}>
9798
<FitViewport.Content>
@@ -100,6 +101,7 @@ function ImageWithCaption({
100101
<ExpandableImage enabled={supportFullscreen && shouldLoad}
101102
imageFile={imageFile}
102103
contentElementId={contentElementId}>
104+
<FilePlaceholder file={imageFile} />
103105
<Image imageFile={imageFile}
104106
load={shouldLoad}
105107
structuredData={true}

0 commit comments

Comments
 (0)