Skip to content

Commit

Permalink
Implementing group exams table which lists past exams.
Browse files Browse the repository at this point in the history
  • Loading branch information
krulis-martin committed Apr 10, 2024
1 parent 1fa02a0 commit 87acb2f
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 11 deletions.
83 changes: 83 additions & 0 deletions src/components/Groups/GroupExamsTable/GroupExamsTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { Table } from 'react-bootstrap';
import { defaultMemoize } from 'reselect';

import DateTime from '../../widgets/DateTime';
import Button from '../../widgets/TheButton';
import { VisibleIcon } from '../../icons';

const sortExams = defaultMemoize(exams => {
const sorted = [...exams];
return sorted.sort((a, b) => a.end - b.end);
});

const GroupExamsTable = ({ exams = null, selected = null, setSelected = null }) =>
exams && exams.length > 0 ? (
<Table className="mb-0">
<thead>
<tr>
<th />
<th>
<FormattedMessage id="app.groupExamsTable.begin" defaultMessage="Begun at" />
</th>
<th>
<FormattedMessage id="app.groupExamsTable.end" defaultMessage="Ended at" />
</th>
<th>
<FormattedMessage id="app.groupExamsTable.lockType" defaultMessage="Lock type" />
</th>
{setSelected && <th />}
</tr>
</thead>
<tbody>
{sortExams(exams).map((exam, idx) => (
<tr key={exam.id} className={selected === exam.id ? 'table-primary' : ''}>
<td className="text-bold">#{idx + 1}</td>
<td>
<DateTime unixts={exam.begin} showRelative showSeconds />
</td>
<td>
<DateTime unixts={exam.end} showRelative showSeconds />
</td>
<td>
<em>
{exam.strict ? (
<FormattedMessage id="app.groupExams.lockStrict" defaultMessage="strict" />
) : (
<FormattedMessage id="app.groupExams.lockRegular" defaultMessage="regular" />
)}
</em>
</td>
{setSelected && (
<td>
<Button
size="xs"
variant="primary"
disabled={selected === exam.id}
onClick={() => setSelected(exam.id)}>
<VisibleIcon visible gapRight />
<FormattedMessage id="app.groupExamsTable.selectButton" defaultMessage="Detail" />
</Button>
</td>
)}
</tr>
))}
</tbody>
</Table>
) : (
<div className="text-center text-muted p-2">
<em>
<FormattedMessage id="app.groupExams.noPreviousExams" defaultMessage="There are no previous exams recorded." />
</em>
</div>
);

GroupExamsTable.propTypes = {
exams: PropTypes.array,
selected: PropTypes.string,
setSelected: PropTypes.func,
};

export default GroupExamsTable;
2 changes: 2 additions & 0 deletions src/components/Groups/GroupExamsTable/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import GroupExamsTable from './GroupExamsTable';
export default GroupExamsTable;
4 changes: 4 additions & 0 deletions src/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,10 @@
"app.groupExams.studentInfoStrict": "Navíc nebudete moct přistupovat k ostatním skupinám dokud budete v uzamčeném režimu.",
"app.groupExams.timeAccuracyWarning": "Lokální hodiny na vašem systému musí být dostatečně seřízené, jinak nemusí tato komponenta fungovat zcela správně.",
"app.groupExams.title": "Zkouškové termíny skupiny",
"app.groupExamsTable.begin": "Začala",
"app.groupExamsTable.end": "Skončila",
"app.groupExamsTable.lockType": "Typ zámku",
"app.groupExamsTable.selectButton": "Detail",
"app.groupInfo.title": "Podrobnosti a metadata skupiny",
"app.groupInvitationForm.expireAt": "Konec platnosti:",
"app.groupInvitationForm.expireAtExplanation": "Odkaz pozvánky bude rozpoznatelný ReCodExem i po uplynutí doby platnosti, ale studenti jej nebudou moci použít.",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,10 @@
"app.groupExams.studentInfoStrict": "Furthermore, you will not be able to access other groups until the exam lock expires.",
"app.groupExams.timeAccuracyWarning": "Your local system clock should be sufficiently synchronized or this component may not work properly.",
"app.groupExams.title": "Group Exam Terms",
"app.groupExamsTable.begin": "Begun at",
"app.groupExamsTable.end": "Ended at",
"app.groupExamsTable.lockType": "Lock type",
"app.groupExamsTable.selectButton": "Detail",
"app.groupInfo.title": "Group Details and Metadata",
"app.groupInvitationForm.expireAt": "Expire at:",
"app.groupInvitationForm.expireAtExplanation": "An invitation link will be still recognized by ReCodEx after the expiration date, but the students will not be allowed to use it.",
Expand Down
17 changes: 6 additions & 11 deletions src/pages/GroupExams/GroupExams.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Page from '../../components/layout/Page';
import { GroupNavigation } from '../../components/layout/Navigation';
import Box from '../../components/widgets/Box';
import GroupArchivedWarning from '../../components/Groups/GroupArchivedWarning';
import GroupExamsTable from '../../components/Groups/GroupExamsTable';
import { GroupExamsIcon } from '../../components/icons';

import { fetchGroup, fetchGroupIfNeeded, setExamPeriod, removeExamPeriod } from '../../redux/modules/groups';
Expand Down Expand Up @@ -70,17 +71,11 @@ class GroupExams extends Component {
</Col>

<Col xs={12} xl={6}>
<Box title={<FormattedMessage id="app.groupExams.listBoxTitle" defaultMessage="Previous exams" />}>
{group.privateData.exams && group.privateData.exams.length > 0 ? null : (
<div className="text-center text-muted p-2">
<em>
<FormattedMessage
id="app.groupExams.noPreviousExams"
defaultMessage="There are no previous exams recorded."
/>
</em>
</div>
)}
<Box
title={<FormattedMessage id="app.groupExams.listBoxTitle" defaultMessage="Previous exams" />}
noPadding
unlimitedHeight>
<GroupExamsTable exams={group.privateData.exams} />
</Box>
</Col>
</Row>
Expand Down

0 comments on commit 87acb2f

Please sign in to comment.