Compare commits
4 Commits
sundas/INF
...
inf-762
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65a5fa2e37 | ||
|
|
f8800de766 | ||
|
|
f7740de54a | ||
|
|
4ca25c14d9 |
@@ -5,6 +5,8 @@ import DOMPurify from 'dompurify';
|
||||
|
||||
import { logError } from '@edx/frontend-platform/logging';
|
||||
|
||||
import { useDebounce } from '../discussions/data/hooks';
|
||||
|
||||
const defaultSanitizeOptions = {
|
||||
USE_PROFILES: { html: true },
|
||||
ADD_ATTR: ['columnalign'],
|
||||
@@ -16,19 +18,21 @@ function HTMLLoader({
|
||||
const sanitizedMath = DOMPurify.sanitize(htmlNode, { ...defaultSanitizeOptions });
|
||||
const previewRef = useRef();
|
||||
|
||||
const debouncedPostContent = useDebounce(htmlNode, 500);
|
||||
|
||||
useEffect(() => {
|
||||
let promise = Promise.resolve(); // Used to hold chain of typesetting calls
|
||||
|
||||
function typeset(code) {
|
||||
promise = promise.then(() => window.MathJax?.typesetPromise(code()))
|
||||
.catch((err) => logError(`Typeset failed: ${err.message}`));
|
||||
return promise;
|
||||
}
|
||||
|
||||
typeset(() => {
|
||||
previewRef.current.innerHTML = sanitizedMath;
|
||||
});
|
||||
}, [htmlNode]);
|
||||
if (debouncedPostContent) {
|
||||
typeset(() => {
|
||||
previewRef.current.innerHTML = sanitizedMath;
|
||||
});
|
||||
}
|
||||
}, [debouncedPostContent]);
|
||||
|
||||
return (
|
||||
<div ref={previewRef} className={cssClassName} id={componentId} data-testid={testId} />
|
||||
|
||||
@@ -119,6 +119,7 @@ export default function TinyMCEEditor(props) {
|
||||
content_css: false,
|
||||
content_style: contentStyle,
|
||||
body_class: 'm-2 text-editor',
|
||||
convert_urls: false,
|
||||
relative_urls: false,
|
||||
default_link_target: '_blank',
|
||||
target_list: false,
|
||||
|
||||
@@ -224,3 +224,24 @@ export const useTourConfiguration = (intl) => {
|
||||
}
|
||||
));
|
||||
};
|
||||
|
||||
export const useDebounce = (value, delay) => {
|
||||
// State and setters for debounced value
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
useEffect(
|
||||
() => {
|
||||
// Update debounced value after delay
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value);
|
||||
}, delay);
|
||||
// Cancel the timeout if value changes (also on delay change or unmount)
|
||||
// This is how we prevent debounced value from updating if value is changed ...
|
||||
// .. within the delay period. Timeout gets cleared and restarted.
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
},
|
||||
[value, delay], // Only re-call effect if value or delay changes
|
||||
);
|
||||
return debouncedValue;
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ function Post({
|
||||
const history = useHistory();
|
||||
const dispatch = useDispatch();
|
||||
const { enableInContextSidebar } = useContext(DiscussionContext);
|
||||
const { courseId } = useSelector((state) => state.courseTabs);
|
||||
const courseId = useSelector((state) => state.config.id);
|
||||
const topic = useSelector(selectTopic(post.topicId));
|
||||
const getTopicSubsection = useSelector(selectorForUnitSubsection);
|
||||
const topicContext = useSelector(selectTopicContext(post.topicId));
|
||||
@@ -126,7 +126,7 @@ function Post({
|
||||
<div className="d-flex mt-14px text-break font-style text-primary-500">
|
||||
<HTMLLoader htmlNode={post.renderedBody} componentId="post" cssClassName="html-loader" testId={post.id} />
|
||||
</div>
|
||||
{topicContext && topic && (
|
||||
{topicContext && (
|
||||
<div
|
||||
className={classNames('mt-14px mb-1 font-style font-size-12',
|
||||
{ 'w-100': enableInContextSidebar })}
|
||||
@@ -137,7 +137,7 @@ function Post({
|
||||
destination={topicContext.unitLink}
|
||||
target="_top"
|
||||
>
|
||||
{enableInContextSidebar
|
||||
{(topicContext && !topic)
|
||||
? (
|
||||
<>
|
||||
<span className="w-auto">{topicContext.chapterName}</span>
|
||||
|
||||
Reference in New Issue
Block a user