Skip to content

Commit e258755

Browse files
authored
Fix #69 Builder - Section Editor - Section selector - Title (#4063)
1 parent 0131442 commit e258755

8 files changed

Lines changed: 339 additions & 70 deletions

File tree

web/client/components/geostory/contents/ContentWrapper.jsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,29 @@
77
*/
88
import React from "react";
99

10+
/**
11+
* Return a class name from props of a content
12+
* @prop {string} theme one of 'bright', 'dark', 'dark-transparent' or 'bright-transparent'
13+
* @prop {string} align one of 'center', 'left' or 'right'
14+
* @prop {string} size one of 'full', 'large', 'medium' or 'small'
15+
*/
16+
const getClassNameFromProps = ({ theme = 'bright', align = 'center', size = 'full' }) => {
17+
const themeClassName = ` ms-${theme}`;
18+
const alignClassName = ` ms-align-${align}`;
19+
const sizeClassName = ` ms-size-${size}`;
20+
return `${themeClassName}${alignClassName}${sizeClassName}`;
21+
};
22+
1023
/**
1124
* Container for all the contents. Is used to:
1225
* - center the content accordingly.
1326
* - Add inViewRef property, to apply IntersectionObserver
1427
*/
15-
export default ({ inViewRef, children, type, contentWrapperStyle }) =>
28+
export default ({ inViewRef, children, type, contentWrapperStyle, ...props }) =>
1629
(<div
1730
ref={inViewRef}
1831
style={contentWrapperStyle}
19-
className={`ms-content ms-content-${type}`}>
32+
className={`ms-content ms-content-${type}${getClassNameFromProps(props)}`}>
2033
<div className="ms-content-body">
2134
{children}
2235
</div>

web/client/components/geostory/contents/__tests__/ContentWrapper-test.jsx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,47 @@ describe('ContentWrapper component', () => {
5050
const el = container.querySelector('.ms-content');
5151
expect(el).toExist();
5252
});
53-
53+
it('test classes generated from default props', () => {
54+
const DEFAULT_THEME_CLASS_NAME = 'ms-bright';
55+
const DEFAULT_ALIGN_CLASS_NAME = 'ms-align-center';
56+
const DEFAULT_SIZE_CLASS_NAME = 'ms-size-full';
57+
ReactDOM.render(<ContentWrapper type="text"/>, document.getElementById("container"));
58+
const container = document.getElementById('container');
59+
const el = container.querySelector('.ms-content');
60+
expect(el).toExist();
61+
expect(el.getAttribute('class')).toBe(`ms-content ms-content-text ${DEFAULT_THEME_CLASS_NAME} ${DEFAULT_ALIGN_CLASS_NAME} ${DEFAULT_SIZE_CLASS_NAME}`);
62+
});
63+
it('test classes generated from theme prop', () => {
64+
const THEME = 'dark';
65+
const THEME_CLASS_NAME = `ms-${THEME}`;
66+
const DEFAULT_ALIGN_CLASS_NAME = 'ms-align-center';
67+
const DEFAULT_SIZE_CLASS_NAME = 'ms-size-full';
68+
ReactDOM.render(<ContentWrapper type="text" theme={THEME}/>, document.getElementById("container"));
69+
const container = document.getElementById('container');
70+
const el = container.querySelector('.ms-content');
71+
expect(el).toExist();
72+
expect(el.getAttribute('class')).toBe(`ms-content ms-content-text ${THEME_CLASS_NAME} ${DEFAULT_ALIGN_CLASS_NAME} ${DEFAULT_SIZE_CLASS_NAME}`);
73+
});
74+
it('test classes generated from align prop', () => {
75+
const ALIGN = 'right';
76+
const DEFAULT_THEME_CLASS_NAME = 'ms-bright';
77+
const ALIGN_CLASS_NAME = `ms-align-${ALIGN}`;
78+
const DEFAULT_SIZE_CLASS_NAME = 'ms-size-full';
79+
ReactDOM.render(<ContentWrapper type="text" align={ALIGN}/>, document.getElementById("container"));
80+
const container = document.getElementById('container');
81+
const el = container.querySelector('.ms-content');
82+
expect(el).toExist();
83+
expect(el.getAttribute('class')).toBe(`ms-content ms-content-text ${DEFAULT_THEME_CLASS_NAME} ${ALIGN_CLASS_NAME} ${DEFAULT_SIZE_CLASS_NAME}`);
84+
});
85+
it('test classes generated from size prop', () => {
86+
const SIZE = 'medium';
87+
const DEFAULT_THEME_CLASS_NAME = 'ms-bright';
88+
const DEFAULT_ALIGN_CLASS_NAME = 'ms-align-center';
89+
const SIZE_CLASS_NAME = `ms-size-${SIZE}`;
90+
ReactDOM.render(<ContentWrapper type="text" size={SIZE}/>, document.getElementById("container"));
91+
const container = document.getElementById('container');
92+
const el = container.querySelector('.ms-content');
93+
expect(el).toExist();
94+
expect(el.getAttribute('class')).toBe(`ms-content ms-content-text ${DEFAULT_THEME_CLASS_NAME} ${DEFAULT_ALIGN_CLASS_NAME} ${SIZE_CLASS_NAME}`);
95+
});
5496
});

web/client/components/geostory/layouts/Cascade.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default ({
3636
{({ width, height }) =>
3737
<div className="ms-sections-container">
3838
{
39-
sections.map(({ contents = [], id: sectionId, type: sectionType }) => {
39+
sections.map(({ contents = [], id: sectionId, type: sectionType, cover }) => {
4040
return (
4141
<Section
4242
key={sectionId}
@@ -46,6 +46,7 @@ export default ({
4646
type={sectionType}
4747
mode={mode}
4848
contents={contents}
49+
cover={cover}
4950
/>
5051
);
5152
})

web/client/components/geostory/layouts/sections/Section.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ class Section extends React.Component {
3434
contents: PropTypes.array,
3535
viewHeight: PropTypes.number,
3636
viewWidth: PropTypes.number,
37-
excludeClassName: PropTypes.string
37+
excludeClassName: PropTypes.string,
38+
cover: PropTypes.boolean
3839
};
3940

4041
static defaultProps = {
@@ -54,6 +55,7 @@ class Section extends React.Component {
5455
return (
5556
<SectionType
5657
mode={this.props.mode}
58+
cover={this.props.cover}
5759
contents={this.props.contents}
5860
viewWidth={this.props.viewWidth}
5961
viewHeight={this.props.viewHeight}/>

web/client/components/geostory/layouts/sections/Title.jsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,30 @@ import React from "react";
99
import Content from '../../contents/Content';
1010
import Background from './Background';
1111
import { backgroundProp } from './enhancers/immersiveBackgroundManager';
12+
import ContainerDimensions from 'react-container-dimensions';
1213
/**
1314
* Paragraph Section Type.
1415
* Paragraph is a page block that expands for all it's height
1516
*/
16-
export default backgroundProp(({ background = {}, contents = [], mode, viewWidth, viewHeight }) => (
17+
export default backgroundProp(({ background = {}, contents = [], mode, cover, viewWidth, viewHeight }) => (
1718
<section
1819
className="ms-section ms-section-title">
19-
<Background
20-
{ ...background }
21-
key={background.id}
22-
width={viewWidth}
23-
height={viewHeight}/>
20+
<ContainerDimensions>
21+
{({ height }) =>
22+
// when section height is less then the view height
23+
// background height need to be equal to section size
24+
// this is important when working with z-index of section
25+
// in case we increase the z-index of title the whole background is visible and overlap next section
26+
<Background
27+
{ ...background }
28+
key={background.id}
29+
width={viewWidth}
30+
height={height >= viewHeight
31+
? viewHeight
32+
: height}/>}
33+
</ContainerDimensions>
2434
<div className="ms-section-contents">
25-
{contents.map((props) => (<Content mode={mode} {...props} contentWrapperStyle={{ minHeight: viewHeight }}/>))}
35+
{contents.map((props) => (<Content mode={mode} {...props} contentWrapperStyle={cover ? { minHeight: viewHeight } : {}}/>))}
2636
</div>
2737
</section>
2838
));

web/client/components/geostory/layouts/sections/__tests__/Title-test.jsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,49 @@ describe('Title component', () => {
4747
expect(img).toExist();
4848
expect(img.getAttribute('src')).toBe(IMAGE_SRC);
4949
});
50+
it('Title rendering cover set to true', () => {
51+
const VIEW_HEIGHT = 500;
52+
const CONTENTS = [
53+
{
54+
id: '000',
55+
type: 'text',
56+
html: '<h1>Title</h1>'
57+
}
58+
];
59+
ReactDOM.render(<Title contents={CONTENTS} viewHeight={VIEW_HEIGHT} cover />, document.getElementById("container"));
60+
const container = document.getElementById('container');
61+
const el = container.querySelector('.ms-section-title');
62+
expect(el).toExist();
63+
64+
const sectionContents = container.querySelector('.ms-section-contents');
65+
expect(sectionContents).toExist();
66+
expect(sectionContents.clientHeight).toBe(VIEW_HEIGHT);
67+
68+
const backgroundContainer = container.querySelector('.ms-section-background-container');
69+
expect(backgroundContainer).toExist();
70+
expect(backgroundContainer.clientHeight).toBe(VIEW_HEIGHT);
71+
});
72+
73+
it('Title rendering cover set to false', () => {
74+
const VIEW_HEIGHT = 500;
75+
const CONTENTS = [
76+
{
77+
id: '000',
78+
type: 'text',
79+
html: '<h1>Title</h1>'
80+
}
81+
];
82+
ReactDOM.render(<Title contents={CONTENTS} viewHeight={VIEW_HEIGHT} cover={false} />, document.getElementById("container"));
83+
const container = document.getElementById('container');
84+
const el = container.querySelector('.ms-section-title');
85+
expect(el).toExist();
86+
87+
const sectionContents = container.querySelector('.ms-section-contents');
88+
expect(sectionContents).toExist();
89+
expect(sectionContents.clientHeight < VIEW_HEIGHT).toBe(true);
90+
91+
const backgroundContainer = container.querySelector('.ms-section-background-container');
92+
expect(backgroundContainer).toExist();
93+
expect(backgroundContainer.clientHeight).toBe(sectionContents.clientHeight);
94+
});
5095
});

web/client/reducers/geostory.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,17 @@ const createSampleSection = () => [{
2626
type: 'title',
2727
id: '000',
2828
title: 'Abstract',
29+
cover: true,
2930
contents: [
3031
{
3132
id: "SomeID",
32-
type: 'text',
3333
background: {
3434
type: "image",
3535
src: 'https://images.unsplash.com/photo-1480843669328-3f7e37d196ae?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80'
3636
},
37-
html: `<h1>Title</h1>`
37+
type: 'text',
38+
theme: 'bright',
39+
html: `<h1 style="text-align:center;">List of Highest Astronomical Observatories</h1><p style="text-align:center;"><em>From Wikipedia, the free encyclopedia</em></p>`
3840
}
3941
]
4042
}, {
@@ -54,7 +56,24 @@ const createSampleSection = () => [{
5456
id: "SomeID2",
5557
type: 'image',
5658
src: 'https://images.unsplash.com/photo-1558999539-7a19738f085d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80',
57-
enableFullscreen: true
59+
enableFullscreen: true,
60+
size: 'medium'
61+
}
62+
]
63+
}, {
64+
type: 'title',
65+
id: '0A0',
66+
title: 'Abstract',
67+
contents: [
68+
{
69+
id: "SomeID",
70+
background: {
71+
type: "image",
72+
src: 'https://images.unsplash.com/photo-1557672172-298e090bd0f1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80'
73+
},
74+
type: 'text',
75+
theme: 'bright',
76+
html: `<h1 style="text-align:center;">Enter title...</h1>`
5877
}
5978
]
6079
}, {
@@ -71,7 +90,9 @@ const createSampleSection = () => [{
7190
src: 'https://images.unsplash.com/photo-1562874724-b33411b38141?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=701&q=80'
7291

7392
},
74-
html: SAMPLE_TEXT
93+
html: SAMPLE_TEXT,
94+
align: 'left',
95+
size: 'small'
7596
}, {
7697
id: "SomeID2",
7798
type: 'text',

0 commit comments

Comments
 (0)