Skip to content

Commit 1fa02a0

Browse files
committed
Implementing a pending exam callout (info panel) with locking button for students.
1 parent 7497ab5 commit 1fa02a0

File tree

19 files changed

+601
-200
lines changed

19 files changed

+601
-200
lines changed

recodex-web.spec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
%define name recodex-web
22
%define short_name web-app
33
%define version 2.10.0
4-
%define unmangled_version 137ce75c61aec51b5c721de71173ae6f67266283
5-
%define release 2
4+
%define unmangled_version 68e609c525256e3def51c63e6e449849c8794ddf
5+
%define release 3
66

77
Summary: ReCodEx web-app component
88
Name: %{name}

src/components/Groups/GroupExamPending/GroupExamPending.js

Lines changed: 145 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
3-
import { FormattedMessage, injectIntl } from 'react-intl';
4-
import { Modal } from 'react-bootstrap';
5-
6-
import ExamForm, {
7-
prepareInitValues as prepareExamInitValues,
8-
transformSubmittedData as transformExamData,
9-
} from '../../forms/ExamForm';
10-
import Button, { TheButtonGroup } from '../../widgets/TheButton';
3+
import { FormattedMessage } from 'react-intl';
4+
5+
import ExamLockButtonContainer from '../../../containers/ExamLockButtonContainer';
116
import Callout from '../../widgets/Callout';
12-
import Icon, { BanIcon, ClockIcon, EditIcon, GroupExamsIcon, LoadingIcon } from '../../icons';
7+
import { InfoIcon, GroupExamsIcon } from '../../icons';
138
import DateTime from '../../widgets/DateTime';
149
import Explanation from '../../widgets/Explanation';
15-
import { getErrorMessage } from '../../../locales/apiErrorMessages';
1610

17-
import { hasPermissions } from '../../../helpers/common';
11+
import { isStudentRole } from '../../helpers/usersRoles';
1812

1913
const REFRESH_INTERVAL = 1; // [s]
2014

@@ -54,47 +48,157 @@ class GroupExamPending extends Component {
5448

5549
render() {
5650
const {
51+
id,
5752
privateData: { examBegin, examEnd, examLockStrict },
58-
currentUser,
53+
currentUser: {
54+
privateData: { groupLock, isGroupLockStrict, ipLock, role },
55+
},
5956
} = this.props;
57+
const isStudent = isStudentRole(role);
6058

61-
//console.log(currentUser);
6259
return (
6360
this.state.isExam && (
64-
<Callout
65-
variant={this.state.examInProgress ? 'danger' : this.state.hasExam ? 'warning' : 'secondary'}
66-
icon={
67-
this.state.examInProgress ? (
68-
<GroupExamsIcon className="fa-beat" />
69-
) : this.state.hasExam ? (
70-
<ClockIcon />
71-
) : null
72-
}>
73-
TODO
74-
{this.state.hasExam && (
75-
<table>
61+
<Callout variant={isStudent && !groupLock ? 'danger' : 'warning'} icon={<GroupExamsIcon />}>
62+
<h4>
63+
{isStudent && groupLock ? (
64+
<FormattedMessage
65+
id="app.groupExams.pending.studentLockedTitle"
66+
defaultMessage="You are locked in for an exam"
67+
/>
68+
) : (
69+
<FormattedMessage
70+
id="app.groupExams.inProgress"
71+
defaultMessage="Exam in progress, the group is in secured mode"
72+
/>
73+
)}
74+
</h4>
75+
76+
{isStudent ? (
77+
<>
78+
{groupLock ? (
79+
<>
80+
<div className="mb-1">
81+
<strong className="mr-2">
82+
<FormattedMessage id="app.groupExams.endAtLong" defaultMessage="Exam ends at" />:
83+
</strong>
84+
<DateTime unixts={examEnd} showRelative />
85+
</div>
86+
87+
<div className="text-muted mb-1">
88+
<FormattedMessage
89+
id="app.groupExams.lockedStudentInfo"
90+
defaultMessage="You may now see and submit solutions to exam assignments."
91+
/>{' '}
92+
{isGroupLockStrict ? (
93+
<FormattedMessage
94+
id="app.groupExams.lockedStudentInfoStrict"
95+
defaultMessage="You may not access any other groups until the exam lock expires."
96+
/>
97+
) : (
98+
<FormattedMessage
99+
id="app.groupExams.lockedStudentInfoRegular"
100+
defaultMessage="You may access other groups in read-only mode until the exam lock expires."
101+
/>
102+
)}
103+
</div>
104+
105+
{ipLock && (
106+
<div className="text-muted mb-1">
107+
<FormattedMessage
108+
id="app.groupExams.ipLockInfo"
109+
defaultMessage="Your actions are restricted to IP address [{ipLock}] until the exam lock expires. Contact your exam supervisor if you require relocation."
110+
values={{ ipLock: <code>{ipLock}</code> }}
111+
/>
112+
</div>
113+
)}
114+
</>
115+
) : (
116+
<table>
117+
<tbody>
118+
<tr>
119+
<td className="pr-5">
120+
<ExamLockButtonContainer groupId={id} size="lg" />
121+
</td>
122+
<td>
123+
<div className="mb-1">
124+
<strong className="mr-2">
125+
<FormattedMessage id="app.groupExams.endAtLong" defaultMessage="Exam ends at" />:
126+
</strong>
127+
<DateTime unixts={examEnd} showRelative />
128+
</div>
129+
130+
<p className="text-muted small">
131+
<InfoIcon gapRight />
132+
<FormattedMessage
133+
id="app.groupExams.studentInfo"
134+
defaultMessage="You need to lock yourself in to see the exam assignments. When locked, your actions will be restricted to your current IP address."
135+
/>{' '}
136+
{examLockStrict ? (
137+
<FormattedMessage
138+
id="app.groupExams.studentInfoStrict"
139+
defaultMessage="Furthermore, you will not be able to access other groups until the exam lock expires."
140+
/>
141+
) : (
142+
<FormattedMessage
143+
id="app.groupExams.studentInfoRegular"
144+
defaultMessage="Furthermore, you will be able to access other groups in a read-only mode until the exam lock expires."
145+
/>
146+
)}
147+
</p>
148+
</td>
149+
</tr>
150+
</tbody>
151+
</table>
152+
)}
153+
154+
<hr className="mb-1" />
155+
<div className="text-muted small">
156+
<FormattedMessage
157+
id="app.groupExams.timeAccuracyWarning"
158+
defaultMessage="Your local system clock should be sufficiently synchronized or this component may not work properly."
159+
/>
160+
</div>
161+
</>
162+
) : (
163+
<table className="w-100">
76164
<tbody>
77165
<tr>
78-
<td className="text-bold p-2">
166+
<td className="text-bold text-nowrap">
79167
<FormattedMessage id="app.groupExams.beginAt" defaultMessage="Begins at" />:
80168
</td>
81-
<td>
169+
<td className="px-2 py-1 text-nowrap">
82170
<DateTime unixts={examBegin} showRelative />
83171
</td>
172+
<td rowSpan={3} className="w-100 p-2 pl-5 text-muted">
173+
<p>
174+
<InfoIcon gapRight />
175+
<FormattedMessage
176+
id="app.groupExams.pending.teacherInfo"
177+
defaultMessage="The exam assignments are currently visible only to students who have lock themselves in the group. "
178+
/>
179+
</p>
180+
<p>
181+
<InfoIcon gapRight />
182+
<FormattedMessage
183+
id="app.groupExams.timeAccuracyWarning"
184+
defaultMessage="Your local system clock should be sufficiently synchronized or this component may not work properly."
185+
/>
186+
</p>
187+
</td>
84188
</tr>
85189
<tr>
86-
<td className="text-bold p-2">
190+
<td className="text-bold text-nowrap">
87191
<FormattedMessage id="app.groupExams.endAt" defaultMessage="Ends at" />:
88192
</td>
89-
<td>
193+
<td className="px-2 py-1 text-nowrap">
90194
<DateTime unixts={examEnd} showRelative />
91195
</td>
92196
</tr>
93197
<tr>
94-
<td className="text-bold p-2">
198+
<td className="text-bold text-nowrap">
95199
<FormattedMessage id="app.groupExams.locking" defaultMessage="Lock type" />:
96200
</td>
97-
<td>
201+
<td className="px-2 py-1 text-nowrap">
98202
<em>
99203
{examLockStrict ? (
100204
<FormattedMessage id="app.groupExams.lockStrict" defaultMessage="strict" />
@@ -135,15 +239,21 @@ class GroupExamPending extends Component {
135239
}
136240

137241
GroupExamPending.propTypes = {
242+
id: PropTypes.string.isRequired,
138243
privateData: PropTypes.shape({
139244
examBegin: PropTypes.number,
140245
examEnd: PropTypes.number,
141246
examLockStrict: PropTypes.bool,
142247
}).isRequired,
143248
archived: PropTypes.bool,
144-
currentUser: PropTypes.object,
145-
//addNotification: PropTypes.func.isRequired,
146-
intl: PropTypes.object,
249+
currentUser: PropTypes.shape({
250+
privateData: PropTypes.shape({
251+
ipLock: PropTypes.string,
252+
groupLock: PropTypes.string,
253+
isGroupLockStrict: PropTypes.bool,
254+
role: PropTypes.string,
255+
}).isRequired,
256+
}),
147257
};
148258

149-
export default injectIntl(GroupExamPending);
259+
export default GroupExamPending;

0 commit comments

Comments
 (0)