Skip to content

Commit bc7b303

Browse files
committed
Fixing react issues with element keys.
1 parent 87c35d7 commit bc7b303

File tree

19 files changed

+256
-83
lines changed

19 files changed

+256
-83
lines changed

src/components/Assignments/Assignment/AssignmentSync/AssignmentSync.js

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ const AssignmentSync = ({ syncInfo, exerciseSync }) => {
2828
values={{
2929
exerciseUpdated: <DateTime unixTs={syncInfo.updatedAt.exercise} emptyPlaceholder="??" />,
3030
assignmentUpdated: <DateTime unixTs={syncInfo.updatedAt.assignment} emptyPlaceholder="??" />,
31-
strong: contents => <strong>{contents}</strong>,
31+
strong: contents => (
32+
<strong key="strong">
33+
{Array.isArray(contents)
34+
? contents.map((c, i) => <React.Fragment key={`${i}`}>{c}</React.Fragment>)
35+
: contents}
36+
</strong>
37+
),
3238
}}
3339
/>
3440
</p>
@@ -39,52 +45,50 @@ const AssignmentSync = ({ syncInfo, exerciseSync }) => {
3945
/>
4046
<ul>{messages}</ul>
4147
</div>
42-
<p>
43-
<TheButtonGroup>
44-
{(syncInfo.localizedTexts?.upToDate === false || syncInfo.fileLinks?.upToDate === false) && (
45-
<Button
46-
variant="primary"
47-
onClick={() => exerciseSync(SYNC_OPTIONS_TEXTS)}
48-
disabled={!syncInfo.isSynchronizationPossible}>
49-
<FormattedMessage id="app.assignment.syncTextsButton" defaultMessage="Update Texts" />
50-
</Button>
51-
)}
52-
53-
{(syncInfo.files?.upToDate === false ||
54-
syncInfo.exerciseTests?.upToDate === false ||
55-
syncInfo.configurationType?.upToDate === false ||
56-
syncInfo.scoreConfig?.upToDate === false ||
57-
syncInfo.exerciseConfig?.upToDate === false ||
58-
syncInfo.runtimeEnvironments?.upToDate === false ||
59-
syncInfo.exerciseEnvironmentConfigs?.upToDate === false ||
60-
syncInfo.hardwareGroups?.upToDate === false ||
61-
syncInfo.limits?.upToDate === false ||
62-
syncInfo.mergeJudgeLogs?.upToDate === false) && (
63-
<Button
64-
variant="primary"
65-
onClick={() => exerciseSync(SYNC_OPTIONS_CONFIG)}
66-
disabled={!syncInfo.isSynchronizationPossible}>
67-
<FormattedMessage id="app.assignment.syncConfigButton" defaultMessage="Update Configuration" />
68-
</Button>
69-
)}
70-
48+
<TheButtonGroup>
49+
{(syncInfo.localizedTexts?.upToDate === false || syncInfo.fileLinks?.upToDate === false) && (
7150
<Button
7251
variant="primary"
73-
onClick={() => exerciseSync(SYNC_OPTIONS_ALL)}
52+
onClick={() => exerciseSync(SYNC_OPTIONS_TEXTS)}
7453
disabled={!syncInfo.isSynchronizationPossible}>
75-
<FormattedMessage id="app.assignment.syncAllButton" defaultMessage="Update Whole Assignment" />
54+
<FormattedMessage id="app.assignment.syncTextsButton" defaultMessage="Update Texts" />
7655
</Button>
77-
</TheButtonGroup>
56+
)}
7857

79-
{!syncInfo.isSynchronizationPossible && (
80-
<span style={{ marginLeft: '2em' }} className="text-body-secondary">
81-
<FormattedMessage
82-
id="app.assignment.syncButton.exerciseBroken"
83-
defaultMessage="The update button is disabled since the exercise is broken. The exercise configuration must be mended first."
84-
/>
85-
</span>
58+
{(syncInfo.files?.upToDate === false ||
59+
syncInfo.exerciseTests?.upToDate === false ||
60+
syncInfo.configurationType?.upToDate === false ||
61+
syncInfo.scoreConfig?.upToDate === false ||
62+
syncInfo.exerciseConfig?.upToDate === false ||
63+
syncInfo.runtimeEnvironments?.upToDate === false ||
64+
syncInfo.exerciseEnvironmentConfigs?.upToDate === false ||
65+
syncInfo.hardwareGroups?.upToDate === false ||
66+
syncInfo.limits?.upToDate === false ||
67+
syncInfo.mergeJudgeLogs?.upToDate === false) && (
68+
<Button
69+
variant="primary"
70+
onClick={() => exerciseSync(SYNC_OPTIONS_CONFIG)}
71+
disabled={!syncInfo.isSynchronizationPossible}>
72+
<FormattedMessage id="app.assignment.syncConfigButton" defaultMessage="Update Configuration" />
73+
</Button>
8674
)}
87-
</p>
75+
76+
<Button
77+
variant="primary"
78+
onClick={() => exerciseSync(SYNC_OPTIONS_ALL)}
79+
disabled={!syncInfo.isSynchronizationPossible}>
80+
<FormattedMessage id="app.assignment.syncAllButton" defaultMessage="Update Whole Assignment" />
81+
</Button>
82+
</TheButtonGroup>
83+
84+
{!syncInfo.isSynchronizationPossible && (
85+
<span className="ms-5 text-body-secondary">
86+
<FormattedMessage
87+
id="app.assignment.syncButton.exerciseBroken"
88+
defaultMessage="The update button is disabled since the exercise is broken. The exercise configuration must be mended first."
89+
/>
90+
</span>
91+
)}
8892
</Callout>
8993
</Col>
9094
</Row>

src/components/Assignments/Assignment/AssignmentSyncIcon/AssignmentSyncIcon.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ const AssignmentSyncIcon = ({ id, syncInfo, ...props }) => {
2727
values={{
2828
exerciseUpdated: <DateTime unixTs={syncInfo.updatedAt.exercise} emptyPlaceholder="??" />,
2929
assignmentUpdated: <DateTime unixTs={syncInfo.updatedAt.assignment} emptyPlaceholder="??" />,
30-
strong: contents => <strong>{contents}</strong>,
30+
strong: contents => (
31+
<strong key="strong">
32+
{Array.isArray(contents)
33+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
34+
: contents}
35+
</strong>
36+
),
3137
}}
3238
/>
3339
</p>

src/components/Assignments/Assignment/AssignmentsTable/AssignmentsTable.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,11 @@ class AssignmentsTable extends Component {
316316
defaultMessage="Total {count} {count, plural, one {assignment} other {assignments}} {count, plural, one {is past its} other {are past their}} deadline. <a>Hide old assignments.</a>"
317317
values={{
318318
count: assignmentsPreprocessedAll.length - assignmentsPreprocessedCurrent.length,
319-
a: content => (
319+
a: contents => (
320320
<a href="" onClick={this.hideOldAssignments}>
321-
{content}
321+
{Array.isArray(contents)
322+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
323+
: contents}
322324
</a>
323325
),
324326
}}
@@ -329,9 +331,11 @@ class AssignmentsTable extends Component {
329331
defaultMessage="There {count, plural, one {is} other {are}} {count} hidden {count, plural, one {assignment} other {assignments}} which {count, plural, one {is past its} other {are past their}} deadline. <a>Show all.</a>"
330332
values={{
331333
count: assignmentsPreprocessedAll.length - assignmentsPreprocessedCurrent.length,
332-
a: content => (
334+
a: contents => (
333335
<a href="" onClick={this.showAllAssignments}>
334-
{content}
336+
{Array.isArray(contents)
337+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
338+
: contents}
335339
</a>
336340
),
337341
}}

src/components/Pipelines/BoxForm/BoxForm.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,16 @@ class BoxForm extends Component {
8080
<FormattedMessage
8181
id="app.pipelines.boxForm.titleEditing"
8282
defaultMessage="Editing Box <strong>{editing}</strong>"
83-
values={{ editing, strong: content => <strong className="ms-1">{content}</strong> }}
83+
values={{
84+
editing,
85+
strong: contents => (
86+
<strong key="strong" className="ms-1">
87+
{Array.isArray(contents)
88+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
89+
: contents}
90+
</strong>
91+
),
92+
}}
8493
/>
8594
) : (
8695
<FormattedMessage id="app.pipelines.boxForm.titleNew" defaultMessage="Add New Box" />
@@ -314,7 +323,13 @@ const validate = (
314323
values={{
315324
type: variable.type,
316325
descType: boxType[ports][portName].type,
317-
code: content => <code>{content}</code>,
326+
code: contents => (
327+
<code>
328+
{Array.isArray(contents)
329+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
330+
: contents}
331+
</code>
332+
),
318333
}}
319334
/>
320335
);

src/components/Pipelines/BoxesTable/BoxesTableRow.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,13 @@ const BoxesTablePortsFragment = ({ box, port, variables, selectedVariable, assig
9393
values={{
9494
type: port.type,
9595
descType: port.prescribedType,
96-
code: content => <code>{content}</code>,
96+
code: contents => (
97+
<code>
98+
{Array.isArray(contents)
99+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
100+
: contents}
101+
</code>
102+
),
97103
}}
98104
/>
99105
}
@@ -112,7 +118,13 @@ const BoxesTablePortsFragment = ({ box, port, variables, selectedVariable, assig
112118
values={{
113119
type: port.type,
114120
descType: port.prescribedType,
115-
code: content => <code>{content}</code>,
121+
code: contents => (
122+
<code>
123+
{Array.isArray(contents)
124+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
125+
: contents}
126+
</code>
127+
),
116128
}}
117129
/>
118130
</small>
@@ -137,7 +149,13 @@ const BoxesTablePortsFragment = ({ box, port, variables, selectedVariable, assig
137149
values={{
138150
type: variables[port.value],
139151
descType: port.prescribedType,
140-
code: content => <code>{content}</code>,
152+
code: contents => (
153+
<code>
154+
{Array.isArray(contents)
155+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
156+
: contents}
157+
</code>
158+
),
141159
}}
142160
/>
143161
}

src/components/Pipelines/VariableForm/VariableForm.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,16 @@ class VariableForm extends Component {
4747
<FormattedMessage
4848
id="app.pipelines.variableForm.titleEditing"
4949
defaultMessage="Editing Variable <strong>{editing}</strong>"
50-
values={{ editing, strong: content => <strong className="ms-1">{content}</strong> }}
50+
values={{
51+
editing,
52+
strong: contents => (
53+
<strong key="strong" className="ms-1">
54+
{Array.isArray(contents)
55+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
56+
: contents}
57+
</strong>
58+
),
59+
}}
5160
/>
5261
) : (
5362
<FormattedMessage id="app.pipelines.variableForm.titleNew" defaultMessage="Add New Variable" />

src/components/Solutions/SolutionStatus/SolutionStatus.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,16 @@ class SolutionStatus extends Component {
628628
<FormattedMessage
629629
id="app.solution.pointsExplainDialog.bonusPoints"
630630
defaultMessage="A supervisor has granted additional <strong>{bonusPoints}</strong> bonus {bonusPoints, plural, one {point} other {points}}."
631-
values={{ bonusPoints, strong: contents => <strong>{contents}</strong> }}
631+
values={{
632+
bonusPoints,
633+
strong: contents => (
634+
<strong key="strong">
635+
{Array.isArray(contents)
636+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
637+
: contents}
638+
</strong>
639+
),
640+
}}
632641
/>
633642
</p>
634643
)}
@@ -639,7 +648,17 @@ class SolutionStatus extends Component {
639648
<FormattedMessage
640649
id="app.solution.pointsExplainDialog.overriddenPoints"
641650
defaultMessage="A supervisor has manually overridden the points to <strong>{overriddenPoints}</strong> (and {bonusPoints} {bonusPoints, plural, one {point} other {points}})."
642-
values={{ overriddenPoints, bonusPoints, strong: contents => <strong>{contents}</strong> }}
651+
values={{
652+
overriddenPoints,
653+
bonusPoints,
654+
strong: contents => (
655+
<strong key="strong">
656+
{Array.isArray(contents)
657+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
658+
: contents}
659+
</strong>
660+
),
661+
}}
643662
/>
644663
</p>
645664
)}

src/components/Solutions/SubmitSolution/SubmitSolution.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,11 @@ class SubmitSolution extends Component {
244244
id="app.submitSolution.linkToWiki"
245245
defaultMessage="Select the right environment, under which you wish to submit your solution. You may find more information about the environments at our <a>wiki page</a>."
246246
values={{
247-
a: caption => (
247+
a: contents => (
248248
<a href={environmentsHelpUrl} target="_blank" rel="noreferrer">
249-
{caption}
249+
{Array.isArray(contents)
250+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
251+
: contents}
250252
</a>
251253
),
252254
}}

src/components/forms/EditEnvironmentConfigForm/EditEnvironmentConfigForm.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,11 @@ class EditEnvironmentConfigForm extends Component {
121121
id="app.editEnvironmentConfig.variablesInfo"
122122
defaultMessage="These variables cover the submitted files and how they are associated with pipeline inputs. Each value may hold a file name or a wildcard (e.g., <code>solution.cpp</code>, <code>*.py</code>, <code>my-*.[c,h]</code>). Only <code>file</code> and <code>file[]</code> variables are allowed here."
123123
values={{
124-
code: text => <code>{text}</code>,
124+
code: text => (
125+
<code>
126+
{Array.isArray(text) ? text.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>) : text}
127+
</code>
128+
),
125129
}}
126130
/>
127131
</p>

src/components/forms/EditEnvironmentSimpleForm/EditEnvironmentSimpleForm.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ class EditEnvironmentSimpleForm extends Component {
9191
id="app.editEnvironmentSimpleForm.linkToWiki"
9292
defaultMessage="Select all runtime environments the exercise should support. You may find more information about the environments at our <a>wiki page</a>."
9393
values={{
94-
a: caption => (
94+
a: contents => (
9595
<a href={environmentsHelpUrl} target="_blank" rel="noreferrer">
96-
{caption}
96+
{Array.isArray(contents)
97+
? contents.map((c, i) => <React.Fragment key={i}>{c}</React.Fragment>)
98+
: contents}
9799
</a>
98100
),
99101
}}

0 commit comments

Comments
 (0)