Skip to content

Commit 5dac8d6

Browse files
committed
Unifying appearance of max points between assignment detail box and assignments table.
1 parent c96d5e0 commit 5dac8d6

File tree

8 files changed

+167
-137
lines changed

8 files changed

+167
-137
lines changed

src/components/Assignments/Assignment/AssignmentDetails/AssignmentDetails.js

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState } from 'react';
22
import PropTypes from 'prop-types';
3-
import { Table, OverlayTrigger, Tooltip, Modal } from 'react-bootstrap';
3+
import { Table, Modal } from 'react-bootstrap';
44
import { FormattedMessage } from 'react-intl';
55

66
import Icon, {
@@ -18,6 +18,7 @@ import DateTime from '../../../widgets/DateTime';
1818
import Explanation from '../../../widgets/Explanation';
1919
import Button from '../../../widgets/TheButton';
2020
import AssignmentDeadlinesGraph from '../AssignmentDeadlinesGraph';
21+
import AssignmentMaxPoints from '../AssignmentMaxPoints';
2122
import { getPointsAtTime } from '../AssignmentDeadlinesGraph/helpers';
2223

2324
const AssignmentDetails = ({
@@ -182,71 +183,13 @@ const AssignmentDetails = ({
182183
)}
183184
</th>
184185
<td>
185-
{allowSecondDeadline && (
186-
<OverlayTrigger
187-
placement="bottom"
188-
overlay={
189-
<Tooltip id="firstDeadlineIconTooltip">
190-
<FormattedMessage
191-
id="app.assignment.maxPointsFirstTooltip"
192-
defaultMessage="Points awarded before the first deadline"
193-
/>
194-
</Tooltip>
195-
}>
196-
<Icon icon="thermometer-full" smallGapRight className="text-muted" />
197-
</OverlayTrigger>
198-
)}
199-
200-
{maxPointsBeforeFirstDeadline}
201-
202-
{allowSecondDeadline && (
203-
<>
204-
{maxPointsDeadlineInterpolation ? (
205-
<OverlayTrigger
206-
placement="bottom"
207-
overlay={
208-
<Tooltip id="interpolationIconTooltip">
209-
<FormattedMessage
210-
id="app.assignment.maxPointsInterpolationTooltip"
211-
defaultMessage="Points between the deadlines are linearly changing towards the second limit"
212-
/>
213-
</Tooltip>
214-
}>
215-
<Icon
216-
icon="long-arrow-alt-right"
217-
gapLeft
218-
gapRight
219-
className="text-primary"
220-
transform={{ rotate: 42 }}
221-
/>
222-
</OverlayTrigger>
223-
) : (
224-
<OverlayTrigger
225-
placement="bottom"
226-
overlay={
227-
<Tooltip id="secondDeadlineIconTooltip">
228-
<FormattedMessage
229-
id="app.assignment.maxPointsSecondTooltip"
230-
defaultMessage="Points awarded between the deadlines"
231-
/>
232-
</Tooltip>
233-
}>
234-
<Icon icon="thermometer-half" largeGapLeft smallGapRight className="text-muted" />
235-
</OverlayTrigger>
236-
)}
237-
{maxPointsBeforeSecondDeadline}
238-
</>
239-
)}
240-
241-
{(allowSecondDeadline || currentPointsLimit !== maxPointsBeforeFirstDeadline) && (
242-
<small className="text-muted ml-3">
243-
<FormattedMessage
244-
id="app.assignment.currentMaxPointsNote"
245-
defaultMessage="({currentPointsLimit} at the moment)"
246-
values={{ currentPointsLimit }}
247-
/>
248-
</small>
249-
)}
186+
<AssignmentMaxPoints
187+
allowSecondDeadline={allowSecondDeadline}
188+
maxPointsDeadlineInterpolation={maxPointsDeadlineInterpolation}
189+
maxPointsBeforeFirstDeadline={maxPointsBeforeFirstDeadline}
190+
maxPointsBeforeSecondDeadline={maxPointsBeforeSecondDeadline}
191+
currentPointsLimit={currentPointsLimit}
192+
/>
250193
</td>
251194
</tr>
252195

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
4+
import { FormattedMessage } from 'react-intl';
5+
6+
import Icon from '../../../icons';
7+
8+
const AssignmentMaxPoints = ({
9+
allowSecondDeadline,
10+
maxPointsBeforeFirstDeadline,
11+
maxPointsBeforeSecondDeadline,
12+
maxPointsDeadlineInterpolation,
13+
currentPointsLimit = null,
14+
}) => (
15+
<>
16+
{allowSecondDeadline ? (
17+
<OverlayTrigger
18+
placement="bottom"
19+
overlay={
20+
<Tooltip id="firstPointsIconTooltip">
21+
<FormattedMessage
22+
id="app.assignment.maxPointsFirstTooltip"
23+
defaultMessage="Points awarded before the first deadline"
24+
/>
25+
</Tooltip>
26+
}>
27+
<span>{maxPointsBeforeFirstDeadline}</span>
28+
</OverlayTrigger>
29+
) : (
30+
maxPointsBeforeFirstDeadline
31+
)}
32+
33+
{allowSecondDeadline && (
34+
<OverlayTrigger
35+
placement="bottom"
36+
overlay={
37+
<Tooltip id="secondPointsIconTooltip">
38+
{maxPointsDeadlineInterpolation ? (
39+
<FormattedMessage
40+
id="app.assignment.maxPointsInterpolationTooltip"
41+
defaultMessage="Points between the deadlines are linearly changing towards the second limit"
42+
/>
43+
) : (
44+
<FormattedMessage
45+
id="app.assignment.maxPointsSecondTooltip"
46+
defaultMessage="Points awarded after the first and before the second deadline"
47+
/>
48+
)}
49+
</Tooltip>
50+
}>
51+
<span>
52+
{maxPointsDeadlineInterpolation ? (
53+
<Icon icon="long-arrow-alt-right" gapLeft smallGapRight className="text-muted" transform={{ rotate: 33 }} />
54+
) : (
55+
<Icon icon="level-down-alt" gapLeft smallGapRight className="text-muted" />
56+
)}
57+
{maxPointsBeforeSecondDeadline}
58+
</span>
59+
</OverlayTrigger>
60+
)}
61+
62+
{currentPointsLimit !== null && (allowSecondDeadline || currentPointsLimit !== maxPointsBeforeFirstDeadline) && (
63+
<small className="text-muted ml-3">
64+
<FormattedMessage
65+
id="app.assignment.currentMaxPointsNote"
66+
defaultMessage="({currentPointsLimit} at the moment)"
67+
values={{ currentPointsLimit }}
68+
/>
69+
</small>
70+
)}
71+
</>
72+
);
73+
74+
AssignmentMaxPoints.propTypes = {
75+
allowSecondDeadline: PropTypes.bool.isRequired,
76+
maxPointsDeadlineInterpolation: PropTypes.bool,
77+
maxPointsBeforeFirstDeadline: PropTypes.number.isRequired,
78+
maxPointsBeforeSecondDeadline: PropTypes.number,
79+
currentPointsLimit: PropTypes.number,
80+
};
81+
82+
export default AssignmentMaxPoints;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './AssignmentMaxPoints';

src/components/Assignments/Assignment/AssignmentTableRow/AssignmentTableRow.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { FormattedMessage, injectIntl } from 'react-intl';
55
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
66

77
import AssignmentStatusIcon from '../AssignmentStatusIcon/AssignmentStatusIcon';
8+
import AssignmentMaxPoints from '../AssignmentMaxPoints';
89
import withLinks from '../../../../helpers/withLinks';
910
import { LocalizedExerciseName } from '../../../helpers/LocalizedNames';
1011
import { ChatIcon, EditIcon, ResultsIcon, MaybeBonusAssignmentIcon, MaybeVisibleAssignmentIcon } from '../../../icons';
@@ -25,6 +26,7 @@ const AssignmentTableRow = ({
2526
maxPointsBeforeFirstDeadline,
2627
secondDeadline,
2728
maxPointsBeforeSecondDeadline,
29+
maxPointsDeadlineInterpolation,
2830
isBonus,
2931
isPublic,
3032
visibleFrom,
@@ -37,6 +39,7 @@ const AssignmentTableRow = ({
3739
isAdmin,
3840
showNames = true,
3941
showGroups = false,
42+
showSecondDeadline = true,
4043
groupsAccessor = null,
4144
discussionOpen,
4245
intl: { locale },
@@ -96,11 +99,21 @@ const AssignmentTableRow = ({
9699
<td className="text-nowrap">
97100
<DateTime unixts={firstDeadline} isDeadline />
98101
</td>
99-
<td className="text-center text-nowrap shrink-col">{maxPointsBeforeFirstDeadline}</td>
100-
<td className="text-nowrap">
101-
<DateTime unixts={allowSecondDeadline ? secondDeadline : null} isDeadline />
102+
103+
{showSecondDeadline && (
104+
<td className="text-nowrap">
105+
<DateTime unixts={allowSecondDeadline ? secondDeadline : null} isDeadline />
106+
</td>
107+
)}
108+
109+
<td className="text-center text-nowrap shrink-col">
110+
<AssignmentMaxPoints
111+
allowSecondDeadline={allowSecondDeadline}
112+
maxPointsDeadlineInterpolation={maxPointsDeadlineInterpolation}
113+
maxPointsBeforeFirstDeadline={maxPointsBeforeFirstDeadline}
114+
maxPointsBeforeSecondDeadline={maxPointsBeforeSecondDeadline}
115+
/>
102116
</td>
103-
<td className="text-center text-nowrap shrink-col">{allowSecondDeadline ? maxPointsBeforeSecondDeadline : ''}</td>
104117

105118
<td className="text-right text-nowrap valign-middle">
106119
<TheButtonGroup>
@@ -172,6 +185,7 @@ AssignmentTableRow.propTypes = {
172185
maxPointsBeforeFirstDeadline: PropTypes.number,
173186
secondDeadline: PropTypes.number,
174187
maxPointsBeforeSecondDeadline: PropTypes.number,
188+
maxPointsDeadlineInterpolation: PropTypes.bool,
175189
isBonus: PropTypes.bool,
176190
isPublic: PropTypes.bool,
177191
visibleFrom: PropTypes.number,
@@ -184,6 +198,7 @@ AssignmentTableRow.propTypes = {
184198
isAdmin: PropTypes.bool,
185199
showNames: PropTypes.bool,
186200
showGroups: PropTypes.bool,
201+
showSecondDeadline: PropTypes.bool,
187202
groupsAccessor: PropTypes.func,
188203
discussionOpen: PropTypes.func,
189204
links: PropTypes.object,

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

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ class AssignmentsTable extends Component {
3636
groupsAccessor = null,
3737
intl: { locale },
3838
} = this.props;
39+
40+
const assignmentsPreprocessed = assignments.filter(isReady).map(getJsData).sort(compareAssignmentsReverted);
41+
const showSecondDeadline = assignmentsPreprocessed.some(assignment => assignment && assignment.secondDeadline);
42+
3943
return (
4044
<>
4145
<Table hover>
@@ -72,13 +76,11 @@ class AssignmentsTable extends Component {
7276
<FormattedMessage id="app.assignments.deadline" defaultMessage="Deadline" />
7377
</th>
7478

75-
<th className="text-nowrap shrink-col">
76-
<FormattedMessage id="app.assignments.maxPointsShort" defaultMessage="Max. points" />
77-
</th>
78-
79-
<th className="text-nowrap shrink-col">
80-
<FormattedMessage id="app.assignments.secondDeadline" defaultMessage="Second deadline" />
81-
</th>
79+
{showSecondDeadline && (
80+
<th className="text-nowrap shrink-col">
81+
<FormattedMessage id="app.assignments.secondDeadline" defaultMessage="Second deadline" />
82+
</th>
83+
)}
8284

8385
<th className="text-nowrap shrink-col">
8486
<FormattedMessage id="app.assignments.maxPointsShort" defaultMessage="Max. points" />
@@ -91,32 +93,27 @@ class AssignmentsTable extends Component {
9193
<tbody>
9294
{assignments.size === 0 && <NoAssignmentTableRow />}
9395

94-
{assignments.some(isLoading) && (
95-
<LoadingAssignmentTableRow colSpan={5 + (assignmentEnvironmentsSelector ? 1 : 0)} />
96-
)}
97-
98-
{assignments
99-
.filter(isReady)
100-
.map(getJsData)
101-
.sort(compareAssignmentsReverted)
102-
.map(assignment => (
103-
<AssignmentTableRow
104-
key={assignment.id}
105-
item={assignment}
106-
runtimeEnvironments={assignmentEnvironmentsSelector && assignmentEnvironmentsSelector(assignment.id)}
107-
userId={userId}
108-
status={fetchAssignmentStatus(statuses, assignment.id)}
109-
locale={locale}
110-
stats={
111-
Object.keys(stats).length !== 0 ? stats.assignments.find(item => item.id === assignment.id) : null
112-
}
113-
isAdmin={isAdmin}
114-
showNames={showNames}
115-
showGroups={showGroups}
116-
groupsAccessor={groupsAccessor}
117-
discussionOpen={() => this.openDialog(assignment)}
118-
/>
119-
))}
96+
{assignments.some(isLoading) && <LoadingAssignmentTableRow colSpan={10} />}
97+
98+
{assignmentsPreprocessed.map(assignment => (
99+
<AssignmentTableRow
100+
key={assignment.id}
101+
item={assignment}
102+
runtimeEnvironments={assignmentEnvironmentsSelector && assignmentEnvironmentsSelector(assignment.id)}
103+
userId={userId}
104+
status={fetchAssignmentStatus(statuses, assignment.id)}
105+
locale={locale}
106+
stats={
107+
Object.keys(stats).length !== 0 ? stats.assignments.find(item => item.id === assignment.id) : null
108+
}
109+
isAdmin={isAdmin}
110+
showNames={showNames}
111+
showGroups={showGroups}
112+
showSecondDeadline={showSecondDeadline}
113+
groupsAccessor={groupsAccessor}
114+
discussionOpen={() => this.openDialog(assignment)}
115+
/>
116+
))}
120117
</tbody>
121118
</Table>
122119

src/locales/cs.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"app.assignment.maxPointsExplanation": "Počet bodů, který dostane zcela správné řešení odevzdané před termínem. Částečně správná řešení dostanou poměrnou část těchto bodů.",
9999
"app.assignment.maxPointsFirstTooltip": "Body přidělované před prvním termínem",
100100
"app.assignment.maxPointsInterpolationTooltip": "Body přidělované mezi termíny se lineárně mění směrem k druhému limitu",
101-
"app.assignment.maxPointsSecondTooltip": "Body přidělované mezi termíny",
101+
"app.assignment.maxPointsSecondTooltip": "Body přidělované po prvním, ale stále před druhým termínem",
102102
"app.assignment.maxPointsTwoLimits": "Bodové limity",
103103
"app.assignment.maxPointsTwoLimitsExplanation": "Skutečný limit se určí podle času odevzdání řešení (tj. zda bylo odevzdáno před prvním termínem, nebo mezi termíny). Limit určuje počet bodů, který dostane zcela správné řešení odevzdané před termínem. Částečně správná řešení dostanou poměrnou část těchto bodů.",
104104
"app.assignment.runtimeEnvironmentsExplanation": "Povolená běhová prostředí (tj. programovací jazyky), která mohou být použita v řešení. Pokud je povoleno více prosředí, řešení musí použít právě jedno z nich (prostředí není možné kombinovat).",
@@ -962,7 +962,6 @@
962962
"app.homepage.githubLink": "GitHub",
963963
"app.homepage.instance.administrator": "Hlavní správce:",
964964
"app.homepage.instance.techSupport": "Kontakt na technickou podporu",
965-
"app.homepage.instance.title": "Instituce",
966965
"app.homepage.quickStart.assignmentsFundamentals": "<strong>Zadané úlohy</strong> jsou úlohy, které byly zadány k řešení v určité skupině. Zadaná úloha obsahuje data zkopírovaná z úlohy — specifikaci (text v markdownu) a řadu konfigurací, které jsou nezbytné pro vyhodnocovací proces odevzdaných řešení. Navíc zadaná úloha obsahuje <strong>termín dokončení</strong> (deadline) a maximální počet <strong>bodů</strong> (tolik bodů je uděleno 100% správnému řešení). Studenti smí odevzdávat řešení i po termínu a tato řešení budou vyhodnocena, ale nebudou jim uděleny žádné body.",
967966
"app.homepage.quickStart.assignmentsSolutionLimitations": "Zadané úlohy určují další omezující podmínky odevzdaným řešením. Pravděpodobně nejdůležitější podmínka je maximální počet pokusů odevzdání. Tento limit je nastaven jednak z důvodu udržení hardwarových nároků systému v rozumných mezích, ale také proto, že filozofie ReCodExu očekává, že studenti budou odevzdávat <strong>hotová</strong> a odladěná řešení a nebudou používat ReCodEx k ladění.",
968967
"app.homepage.quickStart.assignmentsTitle": "Zadané úlohy",

src/locales/en.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"app.assignment.maxPointsExplanation": "The amount of points awarded to completely correct solutions submitted before deadline. Solutions with lower correctness are granted relative portion of these points.",
9999
"app.assignment.maxPointsFirstTooltip": "Points awarded before the first deadline",
100100
"app.assignment.maxPointsInterpolationTooltip": "Points between the deadlines are linearly changing towards the second limit",
101-
"app.assignment.maxPointsSecondTooltip": "Points awarded between the deadlines",
101+
"app.assignment.maxPointsSecondTooltip": "Points awarded after the first and before the second deadline",
102102
"app.assignment.maxPointsTwoLimits": "Points limits",
103103
"app.assignment.maxPointsTwoLimitsExplanation": "The actual limit is determined by the time of submission (i.e., whether it was before the first deadline or between the deadlines). The points limit applies to completely correct solutions, solutions with lower correctness are granted relative portion of these points.",
104104
"app.assignment.runtimeEnvironmentsExplanation": "Allowed runtime environments (i.e., programming languages) that can be used for creating solutions. If multiple environments are allowed, the solution must choose only one (it is not possible to create crossover solutions).",
@@ -962,7 +962,6 @@
962962
"app.homepage.githubLink": "GitHub",
963963
"app.homepage.instance.administrator": "Administrator:",
964964
"app.homepage.instance.techSupport": "Technical support contact",
965-
"app.homepage.instance.title": "Institution",
966965
"app.homepage.quickStart.assignmentsFundamentals": "<strong>Assignments</strong> are exercises assigned to particular group. An assignment holds copied data of the exercise — a specification (text in markdown) and various configurations which govern the evaluation process of submitted solutions. In addition, the assignment is given a <strong>deadline</strong> and maximal amount of <strong>points</strong> (points awarded for 100% correct solutions). Solutions submitted after the deadline are are still evaluated, but they are awarded no points.",
967966
"app.homepage.quickStart.assignmentsSolutionLimitations": "Assignments employ additional limitations on submissions. The most important one is the maximal number of submissions per student. This limit is mainly imposed to keep the hardware demands of the evaluation system reasonable. Furthermore, the philosophy of the ReCodEx is that the students should submit <strong>finished</strong> solutions, not use ReCodEx for debugging.",
968967
"app.homepage.quickStart.assignmentsTitle": "Assignments",

0 commit comments

Comments
 (0)