fix: post content vertical scroll issue

This commit is contained in:
Awais Ansari
2022-09-29 20:36:58 +05:00
committed by Mehak Nasir
parent 59740948c5
commit de81833f9a
6 changed files with 60 additions and 47 deletions

View File

@@ -1,5 +1,7 @@
/* eslint-disable import/prefer-default-export */
import { useContext, useEffect, useRef } from 'react';
import {
useContext, useEffect, useRef, useState,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory, useLocation, useRouteMatch } from 'react-router';
@@ -13,7 +15,7 @@ import { fetchCourseBlocks } from '../../data/thunks';
import { clearRedirect } from '../posts/data';
import { selectTopics } from '../topics/data/selectors';
import { fetchCourseTopics } from '../topics/data/thunks';
import { discussionsPath, postMessageToParent } from '../utils';
import { discussionsPath } from '../utils';
import {
selectAreThreadsFiltered, selectLearnersTabEnabled,
selectModerationSettings,
@@ -99,58 +101,37 @@ export function useIsOnXLDesktop() {
return windowSize.width >= breakpoints.extraLarge.minWidth;
}
/**
* Given an element this attempts to get the height of the entire UI.
*
* @param element
* @returns {number}
*/
function getOuterHeight(element) {
// This is the height of the entire document body.
const bodyHeight = document.body.offsetHeight;
// This is the height of the container that will scroll.
const elementContainerHeight = element.parentNode.clientHeight;
// The difference between the body height and the container height is the size of the header footer etc.
// Add to that the element's own height and we get the size the UI should be to fit everything.
return bodyHeight - elementContainerHeight + element.scrollHeight + 10;
}
/**
* This hook posts a resize message to the parent window if running in an iframe
* @param refContainer reference to the component whose size is to be measured
*/
export function useContainerSizeForParent(refContainer) {
function postResizeMessage(height) {
postMessageToParent('plugin.resize', { height });
}
const location = useLocation();
const enabled = window.parent !== window;
const [height, setHeight] = useState();
const resizeObserver = useRef(new ResizeObserver(() => {
/* istanbul ignore if: ResizeObserver isn't available in the testing env */
if (refContainer.current) {
postResizeMessage(getOuterHeight(refContainer.current));
setHeight(refContainer.current.clientHeight);
}
}));
useEffect(() => {
const container = refContainer.current;
const observer = resizeObserver.current;
if (container && observer && enabled) {
if (container && observer) {
observer.observe(container);
postResizeMessage(getOuterHeight(container));
setHeight(container.clientHeight);
}
return () => {
if (container && observer && enabled) {
if (container && observer) {
observer.unobserve(container);
// Send a message to reset the size so that navigating to another
// page doesn't cause the size to be retained
postResizeMessage(null);
}
};
}, [refContainer, resizeObserver, location]);
return height;
}
export const useAlertBannerVisible = (content) => {

View File

@@ -1,4 +1,4 @@
import React, { useContext, useRef } from 'react';
import React, { useContext } from 'react';
import { useSelector } from 'react-redux';
import { Route, Switch } from 'react-router';
@@ -11,7 +11,7 @@ import { ArrowBack } from '@edx/paragon/icons';
import { PostsPages, Routes } from '../../data/constants';
import { CommentsView } from '../comments';
import { DiscussionContext } from '../common/context';
import { useContainerSizeForParent, useIsOnDesktop } from '../data/hooks';
import { useIsOnDesktop } from '../data/hooks';
import messages from '../messages';
import { PostEditor } from '../posts';
import { discussionsPath } from '../utils';
@@ -19,17 +19,15 @@ import { discussionsPath } from '../utils';
function DiscussionContent({ intl }) {
const location = useLocation();
const history = useHistory();
const refContainer = useRef(null);
const postEditorVisible = useSelector((state) => state.threads.postEditorVisible);
const isOnDesktop = useIsOnDesktop();
const {
courseId, learnerUsername, category, topicId, page,
} = useContext(DiscussionContext);
useContainerSizeForParent(refContainer);
return (
<div className="d-flex bg-light-400 flex-column w-75 w-xs-100 w-xl-75 align-items-center h-100 overflow-auto">
<div className="d-flex flex-column w-100" ref={refContainer}>
<div className="d-flex bg-light-400 flex-column w-75 w-xs-100 w-xl-75 align-items-center">
<div className="d-flex flex-column w-100">
{!isOnDesktop && (
<IconButton
src={ArrowBack}

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
@@ -8,23 +8,39 @@ import {
} from 'react-router';
import { RequestStatus, Routes } from '../../data/constants';
import { useIsOnDesktop, useIsOnXLDesktop, useShowLearnersTab } from '../data/hooks';
import {
useContainerSizeForParent, useIsOnDesktop, useIsOnXLDesktop, useShowLearnersTab,
} from '../data/hooks';
import { selectconfigLoadingStatus } from '../data/selectors';
import { LearnerPostsView, LearnersView } from '../learners';
import { PostsView } from '../posts';
import { TopicsView } from '../topics';
export default function DiscussionSidebar({ displaySidebar }) {
export default function DiscussionSidebar({ displaySidebar, postActionBarRef }) {
const location = useLocation();
const isOnDesktop = useIsOnDesktop();
const isOnXLDesktop = useIsOnXLDesktop();
const configStatus = useSelector(selectconfigLoadingStatus);
const redirectToLearnersTab = useShowLearnersTab();
const sidebarRef = useRef(null);
const postActionBarHeight = useContainerSizeForParent(postActionBarRef);
useEffect(() => {
if (sidebarRef && postActionBarHeight) {
if (isOnDesktop) {
sidebarRef.current.style.maxHeight = `${document.body.offsetHeight - postActionBarHeight}px`;
}
sidebarRef.current.style.minHeight = `${document.body.offsetHeight - postActionBarHeight}px`;
sidebarRef.current.style.top = `${postActionBarHeight}px`;
}
}, [sidebarRef, postActionBarHeight]);
return (
<div
className={classNames('flex-column', {
ref={sidebarRef}
className={classNames('flex-column min-content-height position-sticky', {
'd-none': !displaySidebar,
'd-flex h-100 overflow-auto': displaySidebar,
'd-flex overflow-auto': displaySidebar,
'w-100': !isOnDesktop,
'sidebar-desktop-width': isOnDesktop && !isOnXLDesktop,
'w-25 sidebar-XL-width': isOnXLDesktop,
@@ -60,8 +76,13 @@ export default function DiscussionSidebar({ displaySidebar }) {
DiscussionSidebar.defaultProps = {
displaySidebar: false,
postActionBarRef: null,
};
DiscussionSidebar.propTypes = {
displaySidebar: PropTypes.bool,
postActionBarRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
]),
};

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
import {
@@ -26,6 +26,7 @@ import InformationBanner from './InformationsBanner';
export default function DiscussionsHome() {
const location = useLocation();
const postActionBarRef = useRef(null);
const postEditorVisible = useSelector(
(state) => state.threads.postEditorVisible,
);
@@ -82,10 +83,10 @@ export default function DiscussionsHome() {
}}
>
{!inIframe && <Header courseOrg={org} courseNumber={courseNumber} courseTitle={courseTitle} />}
<main className="container-fluid d-flex flex-column p-0 h-100 w-100 overflow-hidden" id="main" tabIndex="-1">
<main className="container-fluid d-flex flex-column p-0 w-100" id="main" tabIndex="-1">
{!inIframe
&& <CourseTabsNavigation activeTab="discussion" courseId={courseId} />}
<div style={{ zIndex: 1, boxShadow: '0px 2px 4px rgb(0 0 0 / 15%), 0px 2px 8px rgb(0 0 0 / 15%)' }}>
<div className="header-action-bar" ref={postActionBarRef}>
<div
className="d-flex flex-row justify-content-between navbar fixed-top"
>
@@ -100,8 +101,8 @@ export default function DiscussionsHome() {
path={[Routes.POSTS.PATH, Routes.TOPICS.CATEGORY]}
component={provider === DiscussionProvider.LEGACY ? LegacyBreadcrumbMenu : BreadcrumbMenu}
/>
<div className="d-flex flex-row overflow-hidden flex-grow-1 h-100">
<DiscussionSidebar displaySidebar={displaySidebar} />
<div className="d-flex flex-row">
<DiscussionSidebar displaySidebar={displaySidebar} postActionBarRef={postActionBarRef} />
{displayContentArea && <DiscussionContent />}
{!displayContentArea && (
<Switch>

View File

@@ -15,7 +15,7 @@ function EmptyPage({
fullWidth = false,
}) {
const containerClasses = classNames(
'justify-content-center align-items-center d-flex w-100 flex-column pt-5',
'min-content-height justify-content-center align-items-center d-flex w-100 flex-column pt-5',
{ 'bg-light-400': !fullWidth },
);

View File

@@ -220,3 +220,15 @@ header {
}
};
}
.min-content-height {
min-height: 80vh;
}
.header-action-bar {
background-color: #fff;
z-index: 1;
box-shadow: 0px 2px 4px rgb(0 0 0 / 15%), 0px 2px 8px rgb(0 0 0 / 15%);
position: sticky;
top: 0;
}