Skip to content

Commit 5070735

Browse files
committed
feat(KUI-1392): refactor memo preview to correspond to components used for published memo
- added components used in kurs-pm-web - rendering function no only handles visible sections
1 parent c277dcc commit 5070735

7 files changed

+147
-148
lines changed

public/css/_preview.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
margin-block-start: 2rem;
6161
margin-block-end: 1rem;
6262
}
63-
.article {
63+
article {
6464
@include prose.prose;
6565
& > h3:first-of-type {
6666
margin-block-start: 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react'
2+
import i18n from '../../../../../i18n'
3+
import { ExtraHeaderHead } from './ContentHead'
4+
import HtmlWrapper from './HtmlWrapper'
5+
6+
function ContentFromNewSectionEditor({ htmlContent = '', title = '', memoLanguageIndex = 0 /* en */ }) {
7+
const { noInfoYetPreview } = i18n.messages[memoLanguageIndex].sourceInfo
8+
9+
return (
10+
<article aria-label={title}>
11+
<ExtraHeaderHead header={title} />
12+
<HtmlWrapper html={htmlContent || `<p><i>${noInfoYetPreview}</i></p>`} />
13+
</article>
14+
)
15+
}
16+
export default ContentFromNewSectionEditor

public/js/app/components/preview/ExtraHeadingContent.jsx

-44
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* eslint-disable react/no-danger */
2+
import React from 'react'
3+
4+
function HtmlWrapper({ id, mode, html }) {
5+
switch (mode) {
6+
case 'inline':
7+
return <span id={id} dangerouslySetInnerHTML={{ __html: html }} />
8+
default:
9+
return <div id={id} dangerouslySetInnerHTML={{ __html: html }} />
10+
}
11+
}
12+
13+
export default HtmlWrapper
+7-17
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,34 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
3-
43
import i18n from '../../../../../i18n'
54
import { context } from '../../util/fieldsByType'
65
import { ContentHead, SubSectionHeaderMessage } from './ContentHead'
6+
import HtmlWrapper from './HtmlWrapper'
77

8-
const Section = ({ contentId, menuId, visibleInMemo, html, memoLangIndex }) => {
9-
const { nothingFetched, insertedSubSection } = i18n.messages[memoLangIndex].sourceInfo
8+
const Section = ({ contentId, menuId, htmlContent, memoLangIndex = 0 /* en */ }) => {
9+
const { noInfoYetPreview, insertedSubSection } = i18n.messages[memoLangIndex].sourceInfo
1010
const fromSyllabus = {
1111
is: context[contentId].source === '(s)',
1212
subHeader: contentId === 'examination' || contentId === 'ethicalApproach',
1313
}
1414
const isAddedSubSection = context[contentId].hasParentTitle && contentId !== 'permanentDisabilitySubSection'
1515
return (
16-
<span id={menuId} key={contentId} className="article">
16+
<article id={menuId} key={contentId} aria-labelledby={isAddedSubSection ? null : contentId}>
1717
{isAddedSubSection ? (
1818
<SubSectionHeaderMessage message={insertedSubSection} />
1919
) : (
2020
<ContentHead contentId={contentId} memoLangIndex={memoLangIndex} fromSyllabus={fromSyllabus} />
2121
)}
22-
<span
23-
style={visibleInMemo ? {} : { display: 'none' }}
24-
dangerouslySetInnerHTML={{
25-
__html: html || `<p><i>${nothingFetched[context[contentId].type]}</i></p>`,
26-
}}
27-
/>
28-
</span>
22+
<HtmlWrapper mode="inline" html={htmlContent || `<p><i>${noInfoYetPreview}</i></p>`} />
23+
</article>
2924
)
3025
}
3126

3227
Section.propTypes = {
3328
contentId: PropTypes.string.isRequired,
3429
menuId: PropTypes.string.isRequired,
35-
visibleInMemo: PropTypes.bool.isRequired,
36-
html: PropTypes.string,
30+
htmlContent: PropTypes.string,
3731
memoLangIndex: PropTypes.oneOf([1, 0]).isRequired,
3832
}
3933

40-
Section.defaultProps = {
41-
html: '',
42-
}
43-
4434
export default Section

public/js/app/pages/PreviewContainer.jsx

+69-86
Original file line numberDiff line numberDiff line change
@@ -18,111 +18,94 @@ import CourseMemoLinks from '../components/preview/CourseMemoLinks'
1818
import CourseLinks from '../components/preview/CourseLinks'
1919
import CourseContacts from '../components/preview/CourseContacts'
2020
import Section from '../components/preview/Section'
21-
import ExtraHeadingContent from '../components/preview/ExtraHeadingContent'
2221

2322
import i18n from '../../../../i18n'
24-
import { context } from '../util/fieldsByType'
23+
import { context, getDefaultSections } from '../util/fieldsByType'
2524
import { concatMemoName, concatHeaderMemoName } from '../util/helpers'
2625
import { seasonStr } from '../utils-shared/helpers'
27-
import { FIRST_VERSION, EMPTY, SERVICE_URL, SAVED_NEW_PARAM, ADMIN_URL } from '../util/constants'
26+
import { FIRST_VERSION, SERVICE_URL, SAVED_NEW_PARAM, ADMIN_URL } from '../util/constants'
2827
import { TYPE, useToast } from '../hooks/useToast'
29-
import {
30-
htmlHasContent,
31-
isStandardHeadingVisibleInPreview,
32-
isExtraHeadingVisibleInPreview,
33-
} from '../util/editorAndPreviewUtils'
28+
import { getAllSectionsAndHeadingsToShowInPreview } from '../util/editorAndPreviewUtils'
29+
import ContentFromNewSectionEditor from '../components/preview/ContentFromNewSectionEditor'
3430

3531
const PROGRESS = 3
3632

37-
const renderAllSections = ({ sections, memoData }) => {
33+
const renderAllSections = ({ memoData }) => {
3834
const memoLanguageIndex = memoData.memoCommonLangAbbr === 'en' ? 0 : 1
3935
const { sectionsLabels } = i18n.messages[memoLanguageIndex]
36+
const { noInfoYetPreview } = i18n.messages[memoLanguageIndex].sourceInfo
4037

41-
const sectionsWithContent = []
42-
sections.forEach(({ id, content, extraHeaderTitle }) => {
43-
content.forEach(contentId => {
44-
const visibleInMemo = isStandardHeadingVisibleInPreview(contentId, context, memoData)
38+
const sections = getDefaultSections()
39+
const sectionsAndContent = getAllSectionsAndHeadingsToShowInPreview({ sections, context, memoData })
4540

46-
if (visibleInMemo && !sectionsWithContent.includes(id)) {
47-
sectionsWithContent.push(id)
48-
}
49-
})
50-
51-
if (extraHeaderTitle && Array.isArray(memoData[extraHeaderTitle])) {
52-
memoData[extraHeaderTitle].forEach(m => {
53-
if (m.visibleInMemo && !sectionsWithContent.includes(id)) {
54-
sectionsWithContent.push(id)
55-
}
56-
})
41+
return sectionsAndContent.map(({ id, standardHeadingIds, extraHeaderTitle, extraHeadingIndices, isEmptySection }) => {
42+
if (isEmptySection) {
43+
return <EmptySection key={id} id={id} sectionsLabels={sectionsLabels} noInfoYetPreview={noInfoYetPreview} />
5744
}
58-
})
5945

60-
return sections.map(({ id, content, extraHeaderTitle }) => {
61-
if (!sectionsWithContent.includes(id)) {
62-
return (
63-
<section key={id} className="section-wrapper">
64-
<h2 id={id} key={'header-' + id}>
65-
{sectionsLabels[id]}
66-
</h2>
67-
<p>
68-
<i>{EMPTY[memoLanguageIndex]}</i>
69-
</p>
70-
</section>
71-
)
72-
}
73-
// Contacts are displayed in the right column
7446
return (
75-
id !== 'contacts' && (
76-
<section key={id} className="section-wrapper">
77-
<h2 id={id} key={'header-' + id}>
78-
{sectionsLabels[id]}
79-
</h2>
80-
{content.map(contentId => {
81-
const menuId = id + '-' + contentId
82-
let contentHtml = memoData[contentId]
83-
84-
const visibleInMemo = isStandardHeadingVisibleInPreview(contentId, context, memoData)
85-
86-
if (visibleInMemo && !htmlHasContent(contentHtml)) contentHtml = `<p><i>${EMPTY[memoLanguageIndex]}</i></p>`
87-
88-
return (
89-
visibleInMemo && (
90-
<Section
91-
memoLangIndex={memoLanguageIndex}
92-
contentId={contentId}
93-
menuId={menuId}
94-
key={contentId}
95-
visibleInMemo={visibleInMemo}
96-
html={contentHtml}
97-
/>
98-
)
99-
)
100-
})}
101-
{extraHeaderTitle &&
102-
Array.isArray(memoData[extraHeaderTitle]) &&
103-
memoData[extraHeaderTitle].map(({ title, htmlContent, isEmptyNew, uKey }, index) => {
104-
const isVisibleInMemo = isExtraHeadingVisibleInPreview(extraHeaderTitle, index, memoData)
105-
106-
return (
107-
isVisibleInMemo && (
108-
<ExtraHeadingContent
109-
contentId={extraHeaderTitle}
110-
key={uKey || extraHeaderTitle}
111-
initialTitle={title}
112-
initialValue={htmlContent}
113-
isEmptyNew={isEmptyNew}
114-
uKey={uKey}
115-
memoLanguageIndex={memoLanguageIndex}
116-
/>
117-
)
118-
)
119-
})}
120-
</section>
121-
)
47+
<SectionWrapper key={id} id={id} sectionsLabels={sectionsLabels}>
48+
<Sections headings={standardHeadingIds} id={id} memoData={memoData} memoLanguageIndex={memoLanguageIndex} />
49+
50+
<ExtraHeaders
51+
headingIndices={extraHeadingIndices}
52+
extraHeaderTitle={extraHeaderTitle}
53+
memoData={memoData}
54+
memoLanguageIndex={memoLanguageIndex}
55+
/>
56+
</SectionWrapper>
12257
)
12358
})
12459
}
12560

61+
const EmptySection = ({ id, sectionsLabels, noInfoYetPreview }) => (
62+
<SectionWrapper id={id} sectionsLabels={sectionsLabels}>
63+
<article>
64+
<p>
65+
<i>{noInfoYetPreview}</i>
66+
</p>
67+
</article>
68+
</SectionWrapper>
69+
)
70+
71+
const SectionWrapper = ({ id, sectionsLabels, children }) => (
72+
<section key={id} aria-labelledby={id} className="section-wrapper">
73+
<h2 id={id} key={'header-' + id}>
74+
{sectionsLabels[id]}
75+
</h2>
76+
{children}
77+
</section>
78+
)
79+
80+
const Sections = ({ headings, id, memoData, memoLanguageIndex }) =>
81+
headings.map(contentId => {
82+
const menuId = id + '-' + contentId
83+
const htmlContent = memoData[contentId]
84+
85+
return (
86+
<Section
87+
memoLangIndex={memoLanguageIndex}
88+
contentId={contentId}
89+
menuId={menuId}
90+
key={contentId}
91+
htmlContent={htmlContent}
92+
/>
93+
)
94+
})
95+
96+
const ExtraHeaders = ({ headingIndices, extraHeaderTitle, memoData, memoLanguageIndex }) =>
97+
headingIndices.map(index => {
98+
const { uKey, title, htmlContent } = memoData[extraHeaderTitle]?.[index] || {}
99+
return (
100+
<ContentFromNewSectionEditor
101+
key={uKey}
102+
title={title}
103+
htmlContent={htmlContent}
104+
memoLanguageIndex={memoLanguageIndex}
105+
/>
106+
)
107+
})
108+
126109
const determineContentFlexibility = () => {
127110
const lastColLastElem = document.getElementById('last-element-which-determines-styles')
128111
if (lastColLastElem) {

public/js/app/util/editorAndPreviewUtils.js

+41
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,44 @@ export const isExtraHeadingVisibleInPreview = (extraHeaderTitle, index, memoData
4343

4444
return storedAsVisible && htmlHasContent(htmlContent)
4545
}
46+
47+
const sectionsToSkip = ['contacts']
48+
49+
export const getAllSectionsAndHeadingsToShowInPreview = ({ sections, context, memoData }) => {
50+
const sectionsAndHeadings = []
51+
sections
52+
.filter(({ id }) => !sectionsToSkip.includes(id))
53+
.forEach(({ id, content, extraHeaderTitle }) => {
54+
sectionsAndHeadings[id] = []
55+
const standardHeadingIds = []
56+
const extraHeadingIndices = []
57+
58+
content.forEach(contentId => {
59+
const visibleInMemo = isStandardHeadingVisibleInPreview(contentId, context, memoData)
60+
61+
if (visibleInMemo) {
62+
standardHeadingIds.push(contentId)
63+
}
64+
})
65+
66+
memoData[extraHeaderTitle]?.forEach((headingObject, index) => {
67+
const visibleInMemo = isExtraHeadingVisibleInPreview(extraHeaderTitle, index, memoData)
68+
69+
if (visibleInMemo) {
70+
extraHeadingIndices.push(index)
71+
}
72+
})
73+
74+
const isEmptySection = standardHeadingIds.length === 0 && extraHeadingIndices.length === 0
75+
76+
sectionsAndHeadings.push({
77+
id,
78+
standardHeadingIds,
79+
extraHeaderTitle,
80+
extraHeadingIndices,
81+
isEmptySection,
82+
})
83+
})
84+
85+
return sectionsAndHeadings
86+
}

0 commit comments

Comments
 (0)