Web: Common: PageLayout: Fixed PageLayout for children logic

This commit is contained in:
Ilya Oleshko 2020-08-11 15:34:00 +03:00
parent fdb4f43028
commit d02afe646a
2 changed files with 223 additions and 145 deletions

View File

@ -6,27 +6,82 @@ import i18n from './i18n';
import { ARTICLE_PINNED_KEY } from "../../constants";
import Article from "./sub-components/article";
import ArticleHeader from "./sub-components/article-header";
import ArticleMainButton from "./sub-components/article-main-button";
import ArticleBody from "./sub-components/article-body";
import SubArticleHeader from "./sub-components/article-header";
import SubArticleMainButton from "./sub-components/article-main-button";
import SubArticleBody from "./sub-components/article-body";
import ArticlePinPanel from "./sub-components/article-pin-panel";
import Section from "./sub-components/section";
import SectionHeader from "./sub-components/section-header";
import SectionFilter from "./sub-components/section-filter";
import SectionBody from "./sub-components/section-body";
import SectionPaging from "./sub-components/section-paging";
import SubSectionHeader from "./sub-components/section-header";
import SubSectionFilter from "./sub-components/section-filter";
import SubSectionBody from "./sub-components/section-body";
import SubSectionBodyContent from "./sub-components/section-body-content";
import SubSectionPaging from "./sub-components/section-paging";
import SectionToggler from "./sub-components/section-toggler";
import { changeLanguage } from '../../utils';
import { changeLanguage } from "../../utils";
function ArticleHeader() {
return null;
}
ArticleHeader.displayName = "ArticleHeader";
function ArticleMainButton() {
return null;
}
ArticleMainButton.displayName = "ArticleMainButton";
function ArticleBody() {
return null;
}
ArticleBody.displayName = "ArticleBody";
function SectionHeader() {
return null;
}
SectionHeader.displayName = "SectionHeader";
function SectionFilter() {
return null;
}
SectionFilter.displayName = "SectionFilter";
function SectionBody() {
return null;
}
SectionBody.displayName = "SectionBody";
function SectionPaging() {
return null;
}
SectionPaging.displayName = "SectionPaging";
class PageLayoutComponent extends React.Component {
static ArticleHeader = ArticleHeader;
static ArticleMainButton = ArticleMainButton;
static ArticleBody = ArticleBody;
static SectionHeader = SectionHeader;
static SectionFilter = SectionFilter;
static SectionBody = SectionBody;
static SectionPaging = SectionPaging;
class PageLayoutComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = this.mapPropsToState(props);
const isArticleVisibleAndPinned = !!localStorage.getItem(
ARTICLE_PINNED_KEY
);
this.state = {
isBackdropVisible: false,
isArticleVisible: isArticleVisibleAndPinned,
isArticlePinned: isArticleVisibleAndPinned
};
}
componentDidMount() {
window.addEventListener("orientationchange", this.orientationChangeHandler);
const articleElement = document.getElementsByTagName('article') && document.getElementsByTagName('article')[0];
const articleElement =
document.getElementsByTagName('article') &&
document.getElementsByTagName('article')[0];
articleElement && this.orientationChangeHandler();
}
@ -39,7 +94,9 @@ class PageLayoutComponent extends React.PureComponent {
if (!articleElement) return;
const isOrientationVertical = !(screen.orientation ? screen.orientation.angle % 180 : window.matchMedia("(orientation: portrait)"));
const isOrientationVertical = !(screen.orientation
? screen.orientation.angle % 180
: window.matchMedia("(orientation: portrait)"));
const isValueExist = !!localStorage.getItem(ARTICLE_PINNED_KEY);
const articleWidth = articleElement.offsetWidth;
const isArticleWide = articleWidth > screen.availWidth - articleWidth;
@ -52,65 +109,6 @@ class PageLayoutComponent extends React.PureComponent {
}
}
componentDidUpdate(prevProps) {
if (this.hasChanges(this.props, prevProps)) {
this.setState(this.mapPropsToState(this.props));
}
}
hasChanges = (currentProps, prevProps) => {
return (
currentProps.articleHeaderContent != prevProps.articleHeaderContent ||
currentProps.articleMainButtonContent != prevProps.articleMainButtonContent ||
currentProps.articleBodyContent != prevProps.articleBodyContent ||
currentProps.sectionHeaderContent != prevProps.sectionHeaderContent ||
currentProps.sectionFilterContent != prevProps.sectionFilterContent ||
currentProps.sectionBodyContent != prevProps.sectionBodyContent ||
currentProps.sectionPagingContent != prevProps.sectionPagingContent
);
};
mapPropsToState = props => {
let isArticleHeaderAvailable = !!props.articleHeaderContent,
isArticleMainButtonAvailable = !!props.articleMainButtonContent,
isArticleBodyAvailable = !!props.articleBodyContent,
isArticleAvailable = isArticleHeaderAvailable || isArticleMainButtonAvailable || isArticleBodyAvailable,
isSectionHeaderAvailable = !!props.sectionHeaderContent,
isSectionFilterAvailable = !!props.sectionFilterContent,
isSectionPagingAvailable = !!props.sectionPagingContent,
isSectionBodyAvailable = !!props.sectionBodyContent || isSectionFilterAvailable || isSectionPagingAvailable,
isSectionAvailable = isSectionHeaderAvailable || isSectionFilterAvailable || isSectionBodyAvailable || isSectionPagingAvailable || isArticleAvailable,
isBackdropAvailable = isArticleAvailable,
isArticleVisibleAndPinned = !!localStorage.getItem(ARTICLE_PINNED_KEY);
let newState = {
isBackdropAvailable: isBackdropAvailable,
isArticleAvailable: isArticleAvailable,
isArticleHeaderAvailable: isArticleHeaderAvailable,
isArticleMainButtonAvailable: isArticleMainButtonAvailable,
isArticleBodyAvailable: isArticleBodyAvailable,
isSectionAvailable: isSectionAvailable,
isSectionHeaderAvailable: isSectionHeaderAvailable,
isSectionFilterAvailable: isSectionFilterAvailable,
isSectionBodyAvailable: isSectionBodyAvailable,
isSectionPagingAvailable: isSectionPagingAvailable,
isBackdropVisible: false,
isArticleVisible: isArticleVisibleAndPinned,
isArticlePinned: isArticleVisibleAndPinned,
articleHeaderContent: props.articleHeaderContent,
articleMainButtonContent: props.articleMainButtonContent,
articleBodyContent: props.articleBodyContent,
sectionHeaderContent: props.sectionHeaderContent,
sectionFilterContent: props.sectionFilterContent,
sectionBodyContent: props.sectionBodyContent,
sectionPagingContent: props.sectionPagingContent
};
return newState;
};
backdropClick = () => {
this.setState({
isBackdropVisible: false,
@ -148,56 +146,144 @@ class PageLayoutComponent extends React.PureComponent {
};
render() {
const { showProgressBar, progressBarValue, progressBarDropDownContent, withBodyScroll, withBodyAutoFocus, progressBarLabel, onDrop, uploadFiles, setSelections, viewAs } = this.props;
const {
onDrop,
progressBarDropDownContent,
progressBarLabel,
progressBarValue,
setSelections,
showProgressBar,
uploadFiles,
viewAs,
withBodyAutoFocus,
withBodyScroll,
children
} = this.props;
let articleHeaderContent = null;
let articleMainButtonContent = null;
let articleBodyContent = null;
let sectionHeaderContent = null;
let sectionFilterContent = null;
let sectionPagingContent = null;
let sectionBodyContent = null;
React.Children.forEach(children, child => {
const childType =
child && child.type && (child.type.displayName || child.type.name);
switch (childType) {
case ArticleHeader.displayName:
articleHeaderContent = child;
break;
case ArticleMainButton.displayName:
articleMainButtonContent = child;
break;
case ArticleBody.displayName:
articleBodyContent = child;
break;
case SectionHeader.displayName:
sectionHeaderContent = child;
break;
case SectionFilter.displayName:
sectionFilterContent = child;
break;
case SectionPaging.displayName:
sectionPagingContent = child;
break;
case SectionBody.displayName:
sectionBodyContent = child;
break;
default:
break;
}
});
const isArticleHeaderAvailable = !!articleHeaderContent,
isArticleMainButtonAvailable = !!articleMainButtonContent,
isArticleBodyAvailable = !!articleBodyContent,
isArticleAvailable =
isArticleHeaderAvailable ||
isArticleMainButtonAvailable ||
isArticleBodyAvailable,
isSectionHeaderAvailable = !!sectionHeaderContent,
isSectionFilterAvailable = !!sectionFilterContent,
isSectionPagingAvailable = !!sectionPagingContent,
isSectionBodyAvailable =
!!sectionBodyContent ||
isSectionFilterAvailable ||
isSectionPagingAvailable,
isSectionAvailable =
isSectionHeaderAvailable ||
isSectionFilterAvailable ||
isSectionBodyAvailable ||
isSectionPagingAvailable ||
isArticleAvailable,
isBackdropAvailable = isArticleAvailable;
return (
<>
{this.state.isBackdropAvailable && (
{isBackdropAvailable && (
<Backdrop
zIndex={400}
visible={this.state.isBackdropVisible}
onClick={this.backdropClick}
/>
)}
{this.state.isArticleAvailable && (
{isArticleAvailable && (
<Article
visible={this.state.isArticleVisible}
pinned={this.state.isArticlePinned}
>
{this.state.isArticleHeaderAvailable && (
<ArticleHeader>
{this.state.articleHeaderContent}
</ArticleHeader>
{isArticleHeaderAvailable && (
<SubArticleHeader>
{articleHeaderContent
? articleHeaderContent.props.children
: null}
</SubArticleHeader>
)}
{this.state.isArticleMainButtonAvailable && (
<ArticleMainButton>
{this.state.articleMainButtonContent}
</ArticleMainButton>
{isArticleMainButtonAvailable && (
<SubArticleMainButton>
{articleMainButtonContent
? articleMainButtonContent.props.children
: null}
</SubArticleMainButton>
)}
{this.state.isArticleBodyAvailable && (
<ArticleBody>{this.state.articleBodyContent}</ArticleBody>
{isArticleBodyAvailable && (
<SubArticleBody>
{articleBodyContent ? articleBodyContent.props.children : null}
</SubArticleBody>
)}
{this.state.isArticleBodyAvailable && (
{isArticleBodyAvailable && (
<ArticlePinPanel
pinned={this.state.isArticlePinned}
pinText={this.props.t('Pin')}
pinText={this.props.t("Pin")}
onPin={this.pinArticle}
unpinText={this.props.t('Unpin')}
unpinText={this.props.t("Unpin")}
onUnpin={this.unpinArticle}
/>
)}
</Article>
)}
{this.state.isSectionAvailable && (
{isSectionAvailable && (
<Section>
{this.state.isSectionHeaderAvailable && (
<SectionHeader isArticlePinned={this.state.isArticlePinned}>{this.state.sectionHeaderContent}</SectionHeader>
{isSectionHeaderAvailable && (
<SubSectionHeader isArticlePinned={this.state.isArticlePinned}>
{sectionHeaderContent
? sectionHeaderContent.props.children
: null}
</SubSectionHeader>
)}
{this.state.isSectionFilterAvailable && (
<SectionFilter className="section-header_filter">{this.state.sectionFilterContent}</SectionFilter>
{isSectionFilterAvailable && (
<SubSectionFilter className="section-header_filter">
{sectionFilterContent
? sectionFilterContent.props.children
: null}
</SubSectionFilter>
)}
{this.state.isSectionBodyAvailable && (
{isSectionBodyAvailable && (
<>
<SectionBody
<SubSectionBody
onDrop={onDrop}
uploadFiles={uploadFiles}
setSelections={setSelections}
@ -206,14 +292,26 @@ class PageLayoutComponent extends React.PureComponent {
pinned={this.state.isArticlePinned}
viewAs={viewAs}
>
{this.state.isSectionFilterAvailable && (
<SectionFilter className="section-body_filter">{this.state.sectionFilterContent}</SectionFilter>
)}
{this.state.sectionBodyContent}
{this.state.isSectionPagingAvailable && (
<SectionPaging>{this.state.sectionPagingContent}</SectionPaging>
{isSectionFilterAvailable && (
<SubSectionFilter className="section-body_filter">
{sectionFilterContent
? sectionFilterContent.props.children
: null}
</SubSectionFilter>
)}
</SectionBody>
<SubSectionBodyContent>
{sectionBodyContent
? sectionBodyContent.props.children
: null}
</SubSectionBodyContent>
{isSectionPagingAvailable && (
<SubSectionPaging>
{sectionPagingContent
? sectionPagingContent.props.children
: null}
</SubSectionPaging>
)}
</SubSectionBody>
{showProgressBar && (
<ProgressBar
className="layout-progress-bar"
@ -225,7 +323,7 @@ class PageLayoutComponent extends React.PureComponent {
</>
)}
{this.state.isArticleAvailable && (
{isArticleAvailable && (
<SectionToggler
visible={!this.state.isArticleVisible}
onClick={this.showArticle}
@ -238,47 +336,8 @@ class PageLayoutComponent extends React.PureComponent {
}
}
const PageLayoutTranslated = withTranslation()(PageLayoutComponent);
const PageLayout = props => {
changeLanguage(i18n);
return <PageLayoutTranslated i18n={i18n} {...props} />
}
PageLayout.propTypes = {
language: PropTypes.string,
}
PageLayoutComponent.propTypes = {
articleHeaderContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
articleMainButtonContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
articleBodyContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
sectionHeaderContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
sectionFilterContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
sectionBodyContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
sectionPagingContent: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
children: PropTypes.any,
withBodyScroll: PropTypes.bool,
withBodyAutoFocus: PropTypes.bool,
t: PropTypes.func,
@ -289,8 +348,7 @@ PageLayoutComponent.propTypes = {
progressBarLabel: PropTypes.string,
onDrop: PropTypes.func,
setSelections: PropTypes.func,
uploadFiles: PropTypes.bool,
viewAs: PropTypes.string
uploadFiles: PropTypes.bool
};
PageLayoutComponent.defaultProps = {
@ -298,5 +356,25 @@ PageLayoutComponent.defaultProps = {
withBodyAutoFocus: false
};
const PageLayoutTranslated = withTranslation()(PageLayoutComponent);
const PageLayout = props => {
changeLanguage(i18n);
return <PageLayoutTranslated i18n={i18n} {...props} />
}
PageLayout.ArticleHeader = ArticleHeader;
PageLayout.ArticleMainButton = ArticleMainButton;
PageLayout.ArticleBody = ArticleBody;
PageLayout.SectionHeader = SectionHeader;
PageLayout.SectionFilter = SectionFilter;
PageLayout.SectionBody = SectionBody;
PageLayout.SectionPaging = SectionPaging;
PageLayout.propTypes = {
language: PropTypes.string,
children: PropTypes.any
}
export default PageLayout;

View File

@ -7,7 +7,7 @@ export { default as Headline } from "./Headline";
export { default as PeopleSelector } from "./PeopleSelector";
export { default as GroupSelector } from "./GroupSelector";
export { default as AdvancedSelector } from './AdvancedSelector';
export { default as PageLayout } from './PageLayout';
export { default as PageLayout } from "./PageLayout";
export { default as Layout } from './Layout';
export { default as ProfileMenu } from './ProfileMenu';
export { default as ErrorContainer } from './ErrorContainer';