Skip to content

Commit 653da87

Browse files
committed
Properly replacing link keys (%%key%%) in localized exercise/assignment specifications.
1 parent 9f62324 commit 653da87

6 files changed

Lines changed: 52 additions & 14 deletions

File tree

src/components/Exercises/ExerciseDetail/ExerciseDetail.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Icon, {
2222
TagIcon,
2323
VisibleIcon,
2424
} from '../../icons';
25-
import { getLocalizedDescription } from '../../../helpers/localizedData.js';
25+
import { getLocalizedDescription, replaceLinkKeysWithUrls } from '../../../helpers/localizedData.js';
2626
import { LocalizedExerciseName } from '../../helpers/LocalizedNames';
2727
import EnvironmentsList from '../../helpers/EnvironmentsList';
2828
import Version from '../../widgets/Version/Version.js';
@@ -33,13 +33,13 @@ const ExerciseDetail = ({
3333
authorId,
3434
adminsIds = [],
3535
groupsIds = [],
36-
description = '',
3736
difficulty,
3837
createdAt,
3938
updatedAt,
4039
version,
4140
forkedFrom = null,
4241
localizedTexts,
42+
localizedTextsLinks,
4343
runtimeEnvironments,
4444
tags,
4545
isPublic,
@@ -105,7 +105,9 @@ const ExerciseDetail = ({
105105
</span>
106106
</th>
107107
<td>
108-
<Markdown source={getLocalizedDescription({ description, localizedTexts }, locale)} />
108+
<Markdown
109+
source={replaceLinkKeysWithUrls(getLocalizedDescription({ localizedTexts }, locale), localizedTextsLinks)}
110+
/>
109111
</td>
110112
</tr>
111113

@@ -276,17 +278,16 @@ const ExerciseDetail = ({
276278

277279
ExerciseDetail.propTypes = {
278280
id: PropTypes.string.isRequired,
279-
name: PropTypes.string.isRequired,
280281
authorId: PropTypes.string.isRequired,
281282
adminsIds: PropTypes.array,
282283
groupsIds: PropTypes.array,
283284
difficulty: PropTypes.string.isRequired,
284-
description: PropTypes.string,
285285
createdAt: PropTypes.number.isRequired,
286286
updatedAt: PropTypes.number.isRequired,
287287
version: PropTypes.number.isRequired,
288288
forkedFrom: PropTypes.object,
289289
localizedTexts: PropTypes.array.isRequired,
290+
localizedTextsLinks: PropTypes.object,
290291
runtimeEnvironments: PropTypes.array.isRequired,
291292
tags: PropTypes.array.isRequired,
292293
isPublic: PropTypes.bool.isRequired,

src/components/helpers/ExternalLinkPreview/ExternalLinkPreview.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { LoadingIcon } from '../../icons';
77
import Markdown from '../../widgets/Markdown';
88
import InsetPanel from '../../widgets/InsetPanel';
99
import Callout from '../../widgets/Callout';
10+
import { replaceLinkKeysWithUrls } from '../../../helpers/localizedData.js';
1011

1112
class ExternalLinkPreview extends Component {
1213
state = {
@@ -115,6 +116,7 @@ class ExternalLinkPreview extends Component {
115116

116117
render() {
117118
const { url, pending, error, text, isMarkdown } = this.state;
119+
const { localizedTextsLinks } = this.props;
118120
return url !== null ? (
119121
<div>
120122
{text && (
@@ -138,7 +140,15 @@ class ExternalLinkPreview extends Component {
138140

139141
{error && <Callout variant="warning">{error}</Callout>}
140142

141-
{text && <div>{isMarkdown ? <Markdown source={text} /> : <pre style={{ marginTop: '20px' }}>{text}</pre>}</div>}
143+
{text && (
144+
<div>
145+
{isMarkdown ? (
146+
<Markdown source={replaceLinkKeysWithUrls(text, localizedTextsLinks)} />
147+
) : (
148+
<pre className="mt-3">{replaceLinkKeysWithUrls(text, localizedTextsLinks)}</pre>
149+
)}
150+
</div>
151+
)}
142152
</div>
143153
) : (
144154
<div />
@@ -148,6 +158,7 @@ class ExternalLinkPreview extends Component {
148158

149159
ExternalLinkPreview.propTypes = {
150160
url: PropTypes.string.isRequired,
161+
localizedTextsLinks: PropTypes.object,
151162
};
152163

153164
export default ExternalLinkPreview;

src/components/helpers/LocalizedTexts/LocalizedTexts.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import Icon from '../../icons';
88
import Markdown from '../../widgets/Markdown';
99
import Callout from '../../widgets/Callout';
1010
import InsetPanel from '../../widgets/InsetPanel';
11-
import { knownLocales } from '../../../helpers/localizedData.js';
11+
import { knownLocales, replaceLinkKeysWithUrls } from '../../../helpers/localizedData.js';
1212
import { UrlContext } from '../../../helpers/contexts.js';
1313

1414
import './LocalizedTexts.css';
1515

16-
const LocalizedTexts = ({ locales = [], noLocalesMessage = null }) => {
16+
const LocalizedTexts = ({ locales = [], noLocalesMessage = null, localizedTextsLinks = null }) => {
1717
const localeTabs = knownLocales
1818
.map(locale => locales.find(l => l.locale === locale))
1919
.filter(tabData => tabData && (tabData.text || tabData.link || tabData.studentHint));
@@ -70,7 +70,7 @@ const LocalizedTexts = ({ locales = [], noLocalesMessage = null }) => {
7070
</div>
7171
)}
7272

73-
{text.trim() !== '' && <Markdown source={text} />}
73+
{text.trim() !== '' && <Markdown source={replaceLinkKeysWithUrls(text, localizedTextsLinks)} />}
7474

7575
{!text.trim() && !link && (
7676
<Callout variant="warning" className="m-3">
@@ -87,7 +87,7 @@ const LocalizedTexts = ({ locales = [], noLocalesMessage = null }) => {
8787
<h4>
8888
<FormattedMessage id="app.localizedTexts.studentHintHeading" defaultMessage="Hint" />
8989
</h4>
90-
<Markdown source={studentHint} />
90+
<Markdown source={replaceLinkKeysWithUrls(studentHint, localizedTextsLinks)} />
9191
</Card.Footer>
9292
)}
9393
</Tab.Pane>
@@ -108,6 +108,7 @@ LocalizedTexts.propTypes = {
108108
})
109109
),
110110
noLocalesMessage: PropTypes.any,
111+
localizedTextsLinks: PropTypes.object,
111112
};
112113

113114
export default LocalizedTexts;

src/helpers/localizedData.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
22
import { FormattedMessage } from 'react-intl';
33

4+
import { API_BASE } from './config.js';
5+
46
export const knownLocalesNames = {
57
cs: 'Čeština',
68
en: 'English',
@@ -97,7 +99,7 @@ export const transformLocalizedTextsFormData = formData => {
9799

98100
/**
99101
* Global template for localizedTexts validation.
100-
* Internal validation for different sets of properties is injedted as function.
102+
* Internal validation for different sets of properties is injected as function.
101103
* @param errors {object} redux-form validation error object, where errors are collected
102104
* @param formData {array} localizedTexts form data
103105
* @param internalValidation {function} injected internal validator called on every enabled localized text
@@ -118,7 +120,7 @@ export const validateLocalizedTextsFormData = (errors, formData, internalValidat
118120
);
119121
}
120122

121-
// Internally validate all enabled verisons...
123+
// Internally validate all enabled versions...
122124
const localizedTextsErrors = [];
123125
let localizedTextsErrorsCount = 0;
124126
formData
@@ -136,3 +138,16 @@ export const validateLocalizedTextsFormData = (errors, formData, internalValidat
136138

137139
return errors;
138140
};
141+
142+
export const replaceLinkKeysWithUrls = (text, linksMap) => {
143+
if (!linksMap) {
144+
return text;
145+
}
146+
147+
let replacedText = text;
148+
Object.keys(linksMap).forEach(linkKey => {
149+
const url = API_BASE + '/uploaded-files/link/' + linksMap[linkKey];
150+
replacedText = replacedText.replaceAll(`%%${linkKey}%%`, url);
151+
});
152+
return replacedText;
153+
};

src/pages/Assignment/Assignment.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ class Assignment extends Component {
170170

171171
{assignment.localizedTexts.length > 0 && (
172172
<div>
173-
<LocalizedTexts locales={assignment.localizedTexts} />
173+
<LocalizedTexts
174+
locales={assignment.localizedTexts}
175+
localizedTextsLinks={assignment.localizedTextsLinks}
176+
/>
174177
</div>
175178
)}
176179
</Col>

src/pages/Exercise/Exercise.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,14 @@ class Exercise extends Component {
161161
<Row>
162162
<Col xl={6}>
163163
<ExerciseDetail {...exercise} forkedFrom={forkedFrom} locale={locale} className="d-flex d-xl-none" />
164-
<div>{exercise.localizedTexts.length > 0 && <LocalizedTexts locales={exercise.localizedTexts} />}</div>
164+
<div>
165+
{exercise.localizedTexts.length > 0 && (
166+
<LocalizedTexts
167+
locales={exercise.localizedTexts}
168+
localizedTextsLinks={exercise.localizedTextsLinks}
169+
/>
170+
)}
171+
</div>
165172
</Col>
166173
<Col xl={6}>
167174
<ExerciseDetail {...exercise} forkedFrom={forkedFrom} locale={locale} className="d-none d-xl-flex" />

0 commit comments

Comments
 (0)