diff --git a/src/locales/cs.json b/src/locales/cs.json
index 31aa94e4c..1504ba2a2 100644
--- a/src/locales/cs.json
+++ b/src/locales/cs.json
@@ -175,6 +175,8 @@
"app.assignments.hideAllButton": "Skrýt studentům",
"app.assignments.hidePastAssignments": "Celkem {count} {count, plural, one {zadaná úloha má} =2 {zadané úlohy mají} =3 {zadané úlohy mají} =4 {zadané úlohy mají} other {zadaných úloh má}} termín v minulosti. Skrýt staré úlohy.",
"app.assignments.invertSelection": "Invertovat",
+ "app.assignments.lockedSubmissions.reason": "Důvod",
+ "app.assignments.lockedSubmissions.title": "Odevzdávání řešení je v tuto chvíli zablokováno",
"app.assignments.maxPoints": "Maximum bodů",
"app.assignments.maxPointsShort": "Max. bodů",
"app.assignments.name": "Název zadání",
diff --git a/src/locales/en.json b/src/locales/en.json
index ac988db2a..7aef8fc60 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -175,6 +175,8 @@
"app.assignments.hideAllButton": "Set Hidden",
"app.assignments.hidePastAssignments": "Total {count} {count, plural, one {assignment} other {assignments}} {count, plural, one {is past its} other {are past their}} deadline. Hide old assignments.",
"app.assignments.invertSelection": "Invert",
+ "app.assignments.lockedSubmissions.reason": "Reason",
+ "app.assignments.lockedSubmissions.title": "Submissions are currently locked out",
"app.assignments.maxPoints": "Max. Points",
"app.assignments.maxPointsShort": "Max. points",
"app.assignments.name": "Assignment name",
diff --git a/src/pages/Assignment/Assignment.js b/src/pages/Assignment/Assignment.js
index 956aa3624..7b7bc2708 100644
--- a/src/pages/Assignment/Assignment.js
+++ b/src/pages/Assignment/Assignment.js
@@ -2,11 +2,12 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, injectIntl } from 'react-intl';
import { Col, Row } from 'react-bootstrap';
import Box from '../../components/widgets/Box';
import Callout from '../../components/widgets/Callout';
+import OptionalPopoverWrapper from '../../components/widgets/OptionalPopoverWrapper';
import { fetchAssignmentIfNeeded, syncWithExercise } from '../../redux/modules/assignments';
import { canSubmit } from '../../redux/modules/canSubmit';
@@ -54,6 +55,11 @@ import LoadingSolutionsTable from '../../components/Assignments/SolutionsTable/L
import FailedLoadingSolutionsTable from '../../components/Assignments/SolutionsTable/FailedLoadingSolutionsTable';
import { hasPermissions } from '../../helpers/common';
+const getReason = ({ lockedReason }, locale) =>
+ typeof lockedReason === 'object'
+ ? lockedReason[locale] || lockedReason.en || Object.values(lockedReason)[0] || 'Reason unknown.'
+ : lockedReason;
+
class Assignment extends Component {
static loadAsync = ({ assignmentId }, dispatch, { userId }) =>
Promise.all([
@@ -99,6 +105,7 @@ class Assignment extends Component {
fetchManyStatus,
assignmentSolversLoading,
assignmentSolverSelector,
+ intl: { locale },
} = this.props;
return (
@@ -179,21 +186,50 @@ class Assignment extends Component {
} resource={canSubmit}>
{canSubmitObj => (
-
+
+ }
+ contents={
+ <>
+
+
+ :
+ {' '}
+ {getReason(canSubmitObj, locale)}
+ >
+ }>
+
+
)}
-
+ {canSubmitObj.canSubmit && (
+
+ )}
)}
@@ -272,30 +308,33 @@ Assignment.propTypes = {
assignmentSolverSelector: PropTypes.func.isRequired,
reloadCanSubmit: PropTypes.func.isRequired,
reloadSolvers: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
};
-export default connect(
- (state, { params: { assignmentId, userId = null } }) => {
- const loggedInUserId = loggedInUserIdSelector(state);
- return {
- assignment: getAssignment(state, assignmentId),
- submitting: isSubmitting(state),
- runtimeEnvironments: assignmentEnvironmentsSelector(state)(assignmentId),
- userId,
- loggedInUserId,
- isStudentOf: loggedUserIsStudentOfSelector(state),
- canSubmit: canSubmitSolution(assignmentId)(state),
- solutions: getUserSolutionsSortedData(state)(userId || loggedInUserId, assignmentId),
- fetchManyStatus: fetchManyUserSolutionsStatus(state)(userId || loggedInUserId, assignmentId),
- assignmentSolversLoading: isAssignmentSolversLoading(state),
- assignmentSolverSelector: getAssignmentSolverSelector(state),
- };
- },
- (dispatch, { params: { assignmentId } }) => ({
- init: userId => () => dispatch(init(userId, assignmentId)),
- loadAsync: userId => Assignment.loadAsync({ assignmentId }, dispatch, { userId }),
- exerciseSync: () => dispatch(syncWithExercise(assignmentId)),
- reloadCanSubmit: () => dispatch(canSubmit(assignmentId)),
- reloadSolvers: (assignmentId, userId) => dispatch(fetchAssignmentSolvers({ assignmentId, userId })),
- })
-)(Assignment);
+export default injectIntl(
+ connect(
+ (state, { params: { assignmentId, userId = null } }) => {
+ const loggedInUserId = loggedInUserIdSelector(state);
+ return {
+ assignment: getAssignment(state, assignmentId),
+ submitting: isSubmitting(state),
+ runtimeEnvironments: assignmentEnvironmentsSelector(state)(assignmentId),
+ userId,
+ loggedInUserId,
+ isStudentOf: loggedUserIsStudentOfSelector(state),
+ canSubmit: canSubmitSolution(assignmentId)(state),
+ solutions: getUserSolutionsSortedData(state)(userId || loggedInUserId, assignmentId),
+ fetchManyStatus: fetchManyUserSolutionsStatus(state)(userId || loggedInUserId, assignmentId),
+ assignmentSolversLoading: isAssignmentSolversLoading(state),
+ assignmentSolverSelector: getAssignmentSolverSelector(state),
+ };
+ },
+ (dispatch, { params: { assignmentId } }) => ({
+ init: userId => () => dispatch(init(userId, assignmentId)),
+ loadAsync: userId => Assignment.loadAsync({ assignmentId }, dispatch, { userId }),
+ exerciseSync: () => dispatch(syncWithExercise(assignmentId)),
+ reloadCanSubmit: () => dispatch(canSubmit(assignmentId)),
+ reloadSolvers: (assignmentId, userId) => dispatch(fetchAssignmentSolvers({ assignmentId, userId })),
+ })
+ )(Assignment)
+);
diff --git a/src/pages/Solution/Solution.js b/src/pages/Solution/Solution.js
index c8e04a70f..478b8be31 100644
--- a/src/pages/Solution/Solution.js
+++ b/src/pages/Solution/Solution.js
@@ -206,29 +206,28 @@ class Solution extends Component {
)}
{isStudent && (
-
-
- } resource={canSubmit}>
- {canSubmitObj => (
-
- )}
-
-
-
-
+
+ {canSubmitObj =>
+ canSubmitObj.canSubmit && (
+
+
+
+
+
+
+ )
+ }
+
)}
{hasPermissions(solution, 'review') &&