diff --git a/src/components/Solutions/SolutionDetail/SolutionDetail.js b/src/components/Solutions/SolutionDetail/SolutionDetail.js index dd0c85a8a..1d06abc5b 100644 --- a/src/components/Solutions/SolutionDetail/SolutionDetail.js +++ b/src/components/Solutions/SolutionDetail/SolutionDetail.js @@ -114,8 +114,7 @@ class SolutionDetail extends Component { submittedAt={createdAt} userId={authorId} submittedBy={submittedBy} - note={note} - description={description} + note={referenceSolution ? description : note} editNote={editNote} accepted={accepted} review={review} diff --git a/src/components/Solutions/SolutionStatus/SolutionStatus.js b/src/components/Solutions/SolutionStatus/SolutionStatus.js index 9e22d1244..dbf9070ca 100644 --- a/src/components/Solutions/SolutionStatus/SolutionStatus.js +++ b/src/components/Solutions/SolutionStatus/SolutionStatus.js @@ -82,7 +82,6 @@ class SolutionStatus extends Component { userId, submittedBy, note, - description, visibility = null, accepted, review = null, @@ -172,48 +171,44 @@ class SolutionStatus extends Component { )} - {referenceSolution ? ( + {(referenceSolution || note.length > 0 || Boolean(editNote)) && ( - + - - : + + {referenceSolution ? ( + <> + : + + ) : ( + <> + + + + + + )} - {description} - - ) : ( - (note.length > 0 || Boolean(editNote)) && ( - - - - - - - - - - - - {note.length > 0 ? ( - note - ) : ( - - - - )} + + {referenceSolution || note.length > 0 ? ( + note + ) : ( + + + + )} - {Boolean(editNote) && ( - - - - )} - - - ) + {Boolean(editNote) && ( + + + + )} + + )} @@ -541,7 +536,14 @@ class SolutionStatus extends Component { - + {referenceSolution ? ( + + ) : ( + + )} @@ -728,7 +730,6 @@ SolutionStatus.propTypes = { }), evaluation: PropTypes.object, note: PropTypes.string, - description: PropTypes.string, visibility: PropTypes.number, accepted: PropTypes.bool, review: PropTypes.shape({ diff --git a/src/containers/ReferenceSolutionActionsContainer/ReferenceSolutionActionsContainer.js b/src/containers/ReferenceSolutionActionsContainer/ReferenceSolutionActionsContainer.js index b1908f64e..5e27b9f07 100644 --- a/src/containers/ReferenceSolutionActionsContainer/ReferenceSolutionActionsContainer.js +++ b/src/containers/ReferenceSolutionActionsContainer/ReferenceSolutionActionsContainer.js @@ -49,7 +49,7 @@ export default connect( (state, { id }) => { return { currentUserId: loggedInUserIdSelector(state), - solution: getReferenceSolution(id)(state), + solution: getReferenceSolution(state, id), visibilityPending: getReferenceSolutionSetVisibilityStatus(state, id), }; }, diff --git a/src/locales/cs.json b/src/locales/cs.json index c6eb30ae3..42c8c757e 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1530,6 +1530,7 @@ "app.referenceSolution.actions.setPromoted": "Propagovat", "app.referenceSolution.actions.setPublic": "Změnit na veřejnou", "app.referenceSolution.actions.unsetPromoted": "Degradovat", + "app.referenceSolution.editDescriptionModalTitle": "Upravit popis řešení", "app.referenceSolution.exerciseBroken": "Úloha je rozbitá, a proto není v tuto chvíli možné nechat toto vzorové řešení znovu vyhodnotit.", "app.referenceSolution.exerciseNoLongerHasEnvironment": "Úloha již nepodporuje běhové prostředí, pod kterým bylo toto řešení odevzdáno. Řešení není možné znovu vyhodnotit.", "app.referenceSolution.title": "Podrobnosti referenčního řešení", @@ -1537,7 +1538,6 @@ "app.referenceSolution.visibility.promoted": "Řešení je prpagováno autorem úlohy (ostatním vedoucím je doporučeno se s ním seznámit).", "app.referenceSolution.visibility.public": "Řešení je viditelné všem vedoucím, kteří vidí detaily úlohy.", "app.referenceSolutionDetail.comments.additionalSwitchNote": "(učitelé, kteří smí vidět toto referenční řešení)", - "app.referenceSolutionDetail.exercise": "Úloha", "app.referenceSolutionDetail.title.details": "Detail referenčního řešení", "app.referenceSolutionDetail.visibility.private": "Privátní", "app.referenceSolutionDetail.visibility.privateExplanation": "Privátní řešení jsou viditelná pouze jejich autorům. Krátkodobé experimenty s úlohou je vhodné udržovat jako privátní řešení, aby ostatní vedoucí nebyli příliš zahlceni nezajímavými zdrojovými kódy.", diff --git a/src/locales/en.json b/src/locales/en.json index a023ebb45..5207bd039 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1530,6 +1530,7 @@ "app.referenceSolution.actions.setPromoted": "Promote", "app.referenceSolution.actions.setPublic": "Make public", "app.referenceSolution.actions.unsetPromoted": "Demote", + "app.referenceSolution.editDescriptionModalTitle": "Edit Solution Description", "app.referenceSolution.exerciseBroken": "The exercise is broken. This reference solution may not be resubmitted at the moment.", "app.referenceSolution.exerciseNoLongerHasEnvironment": "The exercise no longer supports the environment for which this solution was evaluated. Resubmission is not possible.", "app.referenceSolution.title": "Reference Solution Detail", @@ -1537,7 +1538,6 @@ "app.referenceSolution.visibility.promoted": "The solution is promoted by the auhor of the exercise (recommended for reading to other supervisors)", "app.referenceSolution.visibility.public": "The solution is visible to all supervisors who can access this exercise.", "app.referenceSolutionDetail.comments.additionalSwitchNote": "(teachers who can see this reference solution)", - "app.referenceSolutionDetail.exercise": "Exercise", "app.referenceSolutionDetail.title.details": "Reference Solution Detail", "app.referenceSolutionDetail.visibility.private": "Private", "app.referenceSolutionDetail.visibility.privateExplanation": "Private solutions are visible only to their author. Experimental and temporary submissions should be kept private so other suprevisors are not overwhelmed with abundance of irrelevant source codes.", diff --git a/src/pages/Assignment/Assignment.js b/src/pages/Assignment/Assignment.js index aaee7363c..84a5eab9d 100644 --- a/src/pages/Assignment/Assignment.js +++ b/src/pages/Assignment/Assignment.js @@ -25,7 +25,7 @@ import { fetchRuntimeEnvironments } from '../../redux/modules/runtimeEnvironment import { getAssignment, - assignmentEnvironmentsSelector, + getAssignmentEnvironments, getUserSolutionsSortedData, } from '../../redux/selectors/assignments'; import { canSubmitSolution } from '../../redux/selectors/canSubmit'; @@ -324,7 +324,7 @@ export default injectIntl( return { assignment: getAssignment(state, assignmentId), submitting: isSubmitting(state), - runtimeEnvironments: assignmentEnvironmentsSelector(state)(assignmentId), + runtimeEnvironments: getAssignmentEnvironments(state, assignmentId), userId, loggedInUserId, currentUser: loggedInUserSelector(state), diff --git a/src/pages/AssignmentSolutions/AssignmentSolutions.js b/src/pages/AssignmentSolutions/AssignmentSolutions.js index e51b491b3..e2333a444 100644 --- a/src/pages/AssignmentSolutions/AssignmentSolutions.js +++ b/src/pages/AssignmentSolutions/AssignmentSolutions.js @@ -52,7 +52,7 @@ import { groupSelector } from '../../redux/selectors/groups'; import { studentsIdsOfGroup } from '../../redux/selectors/usersGroups'; import { getAssignment, - assignmentEnvironmentsSelector, + getAssignmentEnvironments, getUserSolutionsSortedData, getAssignmentSolutions, } from '../../redux/selectors/assignments'; @@ -698,7 +698,7 @@ export default withLinks( getUserSolutions: userId => getUserSolutionsSortedData(state)(userId, assignmentId), assignmentSolutions: getAssignmentSolutions(state, assignmentId), getGroup: id => groupSelector(state, id), - runtimeEnvironments: assignmentEnvironmentsSelector(state)(assignmentId), + runtimeEnvironments: getAssignmentEnvironments(state, assignmentId), fetchManyStatus: fetchManyAssignmentSolutionsStatus(assignmentId)(state), assignmentSolversLoading: isAssignmentSolversLoading(state), assignmentSolverSelector: getAssignmentSolverSelector(state), diff --git a/src/pages/ReferenceSolution/ReferenceSolution.js b/src/pages/ReferenceSolution/ReferenceSolution.js index 3f09c37c6..8f281538a 100644 --- a/src/pages/ReferenceSolution/ReferenceSolution.js +++ b/src/pages/ReferenceSolution/ReferenceSolution.js @@ -16,7 +16,11 @@ import { TheButtonGroup } from '../../components/widgets/TheButton'; import Callout from '../../components/widgets/Callout'; import { ReferenceSolutionIcon } from '../../components/icons'; -import { fetchReferenceSolutionIfNeeded, fetchReferenceSolution } from '../../redux/modules/referenceSolutions'; +import { + fetchReferenceSolutionIfNeeded, + fetchReferenceSolution, + setDescription, +} from '../../redux/modules/referenceSolutions'; import { fetchReferenceSolutionFilesIfNeeded } from '../../redux/modules/solutionFiles'; import { download } from '../../redux/modules/files'; import { fetchExerciseIfNeeded } from '../../redux/modules/exercises'; @@ -70,6 +74,7 @@ class ReferenceSolution extends Component { exercise, fetchStatus, evaluations, + editNote, refreshSolutionEvaluations, deleteEvaluation, scoreConfigSelector, @@ -144,6 +149,7 @@ class ReferenceSolution extends Component { runtimeEnvironments={exercise.runtimeEnvironments} currentUser={currentUser} exercise={exercise} + editNote={hasPermissions(referenceSolution, 'update') ? editNote : null} scoreConfigSelector={scoreConfigSelector} download={download} deleteEvaluation={deleteEvaluation} @@ -173,6 +179,7 @@ ReferenceSolution.propTypes = { referenceSolution: ImmutablePropTypes.map, files: ImmutablePropTypes.map, exercise: ImmutablePropTypes.map, + editNote: PropTypes.func.isRequired, refreshSolutionEvaluations: PropTypes.func, deleteEvaluation: PropTypes.func.isRequired, download: PropTypes.func.isRequired, @@ -186,16 +193,17 @@ export default injectIntl( connect( (state, { params: { exerciseId, referenceSolutionId } }) => ({ currentUser: loggedInUserSelector(state), - referenceSolution: getReferenceSolution(referenceSolutionId)(state), + referenceSolution: getReferenceSolution(state, referenceSolutionId), files: getSolutionFiles(state, referenceSolutionId), exercise: getExercise(exerciseId)(state), - evaluations: evaluationsForReferenceSolutionSelector(referenceSolutionId)(state), + evaluations: evaluationsForReferenceSolutionSelector(state, referenceSolutionId), fetchStatus: fetchManyStatus(referenceSolutionId)(state), scoreConfigSelector: referenceSubmissionScoreConfigSelector(state), }), (dispatch, { params }) => ({ loadAsync: () => ReferenceSolution.loadAsync(params, dispatch), fetchScoreConfigIfNeeded: submissionId => dispatch(fetchReferenceSubmissionScoreConfigIfNeeded(submissionId)), + editNote: note => dispatch(setDescription(params.referenceSolutionId, note)), refreshSolutionEvaluations: () => { dispatch(fetchReferenceSolution(params.referenceSolutionId)); dispatch(fetchReferenceSolutionEvaluationsForSolution(params.referenceSolutionId)); diff --git a/src/pages/Solution/Solution.js b/src/pages/Solution/Solution.js index bd81b03fe..eced3b24a 100644 --- a/src/pages/Solution/Solution.js +++ b/src/pages/Solution/Solution.js @@ -46,7 +46,7 @@ import { getSolution, isAssignmentSolversLoading, getAssignmentSolverSelector } import { getSolutionFiles } from '../../redux/selectors/solutionFiles'; import { getAssignment, - assignmentEnvironmentsSelector, + getAssignmentEnvironments, getUserSolutionsSortedData, } from '../../redux/selectors/assignments'; import { evaluationsForSubmissionSelector, fetchManyStatus } from '../../redux/selectors/submissionEvaluations'; @@ -338,7 +338,7 @@ export default connect( canSubmit: canSubmitSolution(assignmentId)(state), assignment: getAssignment(state, assignmentId), evaluations: evaluationsForSubmissionSelector(state, solutionId), - runtimeEnvironments: assignmentEnvironmentsSelector(state)(assignmentId), + runtimeEnvironments: getAssignmentEnvironments(state, assignmentId), fetchStatus: fetchManyStatus(solutionId)(state), scoreConfigSelector: assignmentSubmissionScoreConfigSelector(state), assignmentSolversLoading: isAssignmentSolversLoading(state), diff --git a/src/pages/SolutionSourceCodes/SolutionSourceCodes.js b/src/pages/SolutionSourceCodes/SolutionSourceCodes.js index b6e691023..13f52851b 100644 --- a/src/pages/SolutionSourceCodes/SolutionSourceCodes.js +++ b/src/pages/SolutionSourceCodes/SolutionSourceCodes.js @@ -47,7 +47,7 @@ import { getSolutionReviewComments } from '../../redux/selectors/solutionReviews import { getAssignment, getUserSolutionsSortedData, - assignmentEnvironmentsSelector, + getAssignmentEnvironments, } from '../../redux/selectors/assignments'; import { getFilesContentSelector } from '../../redux/selectors/files'; import { getLoggedInUserEffectiveRole, loggedInUserSelector } from '../../redux/selectors/users'; @@ -733,7 +733,7 @@ export default withRouter( loggedUserId: loggedInUserIdSelector(state), currentUser: loggedInUserSelector(state), effectiveRole: getLoggedInUserEffectiveRole(state), - runtimeEnvironments: assignmentEnvironmentsSelector(state)(assignmentId), + runtimeEnvironments: getAssignmentEnvironments(state, assignmentId), isPrimaryAdminOf: loggedUserIsPrimaryAdminOfSelector(state), }; }, diff --git a/src/redux/modules/referenceSolutions.js b/src/redux/modules/referenceSolutions.js index 367d01e3b..22dfe31c0 100644 --- a/src/redux/modules/referenceSolutions.js +++ b/src/redux/modules/referenceSolutions.js @@ -25,6 +25,7 @@ export const additionalActionTypes = { RESUBMIT: 'recodex/referenceSolutions/RESUBMIT', FETCHALL: 'recodex/referenceSolutions/FETCHALL', FETCHALL_FULFILLED: 'recodex/referenceSolutions/FETCHALL_FULFILLED', + ...createActionsWithPostfixes('SET_NOTE', 'recodex/referenceSolutions'), ...createActionsWithPostfixes('SET_VISIBILITY', 'recodex/referenceSolutions'), }; @@ -52,6 +53,15 @@ export const resubmitReferenceSolution = (solutionId, progressObserverId = null, }, }); +export const setDescription = (solutionId, note) => + createApiAction({ + type: additionalActionTypes.SET_NOTE, + endpoint: `/reference-solutions/${solutionId}`, + method: 'POST', + body: { note }, + meta: { solutionId }, + }); + export const setVisibility = (solutionId, visibility = 1) => createApiAction({ type: additionalActionTypes.SET_VISIBILITY, @@ -101,6 +111,15 @@ const reducer = handleActions( ) : state, + [additionalActionTypes.SET_NOTE_FULFILLED]: (state, { payload }) => + state.setIn( + ['resources', payload.id], + createRecord({ + state: resourceStatus.FULFILLED, + data: payload, + }) + ), + [additionalActionTypes.SET_VISIBILITY_PENDING]: (state, { meta: { solutionId } }) => state.setIn(['resources', solutionId, 'visibility'], true), [additionalActionTypes.SET_VISIBILITY_REJECTED]: (state, { meta: { solutionId } }) => diff --git a/src/redux/modules/solutions.js b/src/redux/modules/solutions.js index d02a48fe9..f51dcc42b 100644 --- a/src/redux/modules/solutions.js +++ b/src/redux/modules/solutions.js @@ -7,6 +7,7 @@ import factory, { defaultNeedsRefetching, createRecord, resourceStatus, + createActionsWithPostfixes, } from '../helpers/resourceManager'; import { actionTypes as submissionActionTypes } from './submission'; import { actionTypes as submissionEvaluationActionTypes } from './submissionEvaluations'; @@ -33,36 +34,15 @@ const { actions, actionTypes, reduceActions } = factory({ */ export { actionTypes }; export const additionalActionTypes = { - LOAD_USERS_SOLUTIONS: 'recodex/solutions/LOAD_USERS_SOLUTIONS', - LOAD_USERS_SOLUTIONS_PENDING: 'recodex/solutions/LOAD_USERS_SOLUTIONS_PENDING', - LOAD_USERS_SOLUTIONS_FULFILLED: 'recodex/solutions/LOAD_USERS_SOLUTIONS_FULFILLED', - LOAD_USERS_SOLUTIONS_REJECTED: 'recodex/solutions/LOAD_USERS_SOLUTIONS_REJECTED', - LOAD_ASSIGNMENT_SOLUTIONS: 'recodex/solutions/LOAD_ASSIGNMENT_SOLUTIONS', - LOAD_ASSIGNMENT_SOLUTIONS_PENDING: 'recodex/solutions/LOAD_ASSIGNMENT_SOLUTIONS_PENDING', - LOAD_ASSIGNMENT_SOLUTIONS_FULFILLED: 'recodex/solutions/LOAD_ASSIGNMENT_SOLUTIONS_FULFILLED', - LOAD_ASSIGNMENT_SOLUTIONS_REJECTED: 'recodex/solutions/LOAD_ASSIGNMENT_SOLUTIONS_REJECTED', - LOAD_GROUP_STUDENTS_SOLUTIONS: 'recodex/solutions/LOAD_GROUP_STUDENTS_SOLUTIONS', - LOAD_GROUP_STUDENTS_SOLUTIONS_PENDING: 'recodex/solutions/LOAD_GROUP_STUDENTS_SOLUTIONS_PENDING', - LOAD_GROUP_STUDENTS_SOLUTIONS_FULFILLED: 'recodex/solutions/LOAD_GROUP_STUDENTS_SOLUTIONS_FULFILLED', - LOAD_GROUP_STUDENTS_SOLUTIONS_REJECTED: 'recodex/solutions/LOAD_GROUP_STUDENTS_SOLUTIONS_REJECTED', - SET_NOTE: 'recodex/solutions/SET_NOTE', - SET_NOTE_PENDING: 'recodex/solutions/SET_NOTE_PENDING', - SET_NOTE_FULFILLED: 'recodex/solutions/SET_NOTE_FULFILLED', - SET_NOTE_REJECTED: 'recodex/solutions/SET_NOTE_REJECTED', - SET_BONUS_POINTS: 'recodex/solutions/SET_BONUS_POINTS', - SET_BONUS_POINTS_PENDING: 'recodex/solutions/SET_BONUS_POINTS_PENDING', - SET_BONUS_POINTS_FULFILLED: 'recodex/solutions/SET_BONUS_POINTS_FULFILLED', - SET_BONUS_POINTS_REJECTED: 'recodex/solutions/SET_BONUS_POINTS_REJECTED', - SET_FLAG: 'recodex/solutions/SET_FLAG', - SET_FLAG_PENDING: 'recodex/solutions/SET_FLAG_PENDING', - SET_FLAG_FULFILLED: 'recodex/solutions/SET_FLAG_FULFILLED', - SET_FLAG_REJECTED: 'recodex/solutions/SET_FLAG_REJECTED', - DOWNLOAD_RESULT_ARCHIVE: 'recodex/files/DOWNLOAD_RESULT_ARCHIVE', - LOAD_ASSIGNMENT_SOLVERS: 'recodex/solutions/LOAD_ASSIGNMENT_SOLVERS', - LOAD_ASSIGNMENT_SOLVERS_PENDING: 'recodex/solutions/LOAD_ASSIGNMENT_SOLVERS_PENDING', - LOAD_ASSIGNMENT_SOLVERS_FULFILLED: 'recodex/solutions/LOAD_ASSIGNMENT_SOLVERS_FULFILLED', - LOAD_ASSIGNMENT_SOLVERS_REJECTED: 'recodex/solutions/LOAD_ASSIGNMENT_SOLVERS_REJECTED', + ...createActionsWithPostfixes('LOAD_USERS_SOLUTIONS', 'recodex/solutions'), + ...createActionsWithPostfixes('LOAD_ASSIGNMENT_SOLUTIONS', 'recodex/solutions'), + ...createActionsWithPostfixes('LOAD_GROUP_STUDENTS_SOLUTIONS', 'recodex/solutions'), + ...createActionsWithPostfixes('SET_NOTE', 'recodex/solutions'), + ...createActionsWithPostfixes('SET_BONUS_POINTS', 'recodex/solutions'), + ...createActionsWithPostfixes('SET_FLAG', 'recodex/solutions'), + ...createActionsWithPostfixes('LOAD_ASSIGNMENT_SOLVERS', 'recodex/solutions'), INVALIDATE_ASSIGNMENT_SOLVERS: 'recodex/solutions/INVALIDATE_ASSIGNMENT_SOLVERS', + DOWNLOAD_RESULT_ARCHIVE: 'recodex/files/DOWNLOAD_RESULT_ARCHIVE', }; export const fetchSolution = actions.fetchResource; diff --git a/src/redux/selectors/assignments.js b/src/redux/selectors/assignments.js index d681f7540..99bc034c8 100644 --- a/src/redux/selectors/assignments.js +++ b/src/redux/selectors/assignments.js @@ -19,20 +19,27 @@ export const getExerciseAssignments = createSelector([getAssignmentResources, ge assignments.filter(assignment => isReady(assignment) && assignment.getIn(['data', 'exerciseId']) === exerciseId) ); +const _getAssignmentEnvironments = (assignmentSelector, envSelector, id) => { + const assignment = assignmentSelector(id); + const envIds = assignment && assignment.getIn(['data', 'runtimeEnvironmentIds']); + const disabledEnvIds = assignment && assignment.getIn(['data', 'disabledRuntimeEnvironmentIds']); + + return envIds && disabledEnvIds && envSelector + ? envIds + .toArray() + .filter(env => !disabledEnvIds.toArray().includes(env)) + .map(envSelector) + : null; +}; + +export const getAssignmentEnvironments = createSelector( + [getAssignmentSelector, runtimeEnvironmentSelector, getParam], + _getAssignmentEnvironments +); + export const assignmentEnvironmentsSelector = createSelector( [getAssignmentSelector, runtimeEnvironmentSelector], - (assignmentSelector, envSelector) => id => { - const assignment = assignmentSelector(id); - const envIds = assignment && assignment.getIn(['data', 'runtimeEnvironmentIds']); - const disabledEnvIds = assignment && assignment.getIn(['data', 'disabledRuntimeEnvironmentIds']); - - return envIds && disabledEnvIds && envSelector - ? envIds - .toArray() - .filter(env => !disabledEnvIds.toArray().includes(env)) - .map(envSelector) - : null; - } + (assignmentSelector, envSelector) => id => _getAssignmentEnvironments(assignmentSelector, envSelector, id) ); export const getAssignmentSolutions = createSelector( diff --git a/src/redux/selectors/referenceSolutionEvaluations.js b/src/redux/selectors/referenceSolutionEvaluations.js index 3f0b6bd6e..379b7ec67 100644 --- a/src/redux/selectors/referenceSolutionEvaluations.js +++ b/src/redux/selectors/referenceSolutionEvaluations.js @@ -6,40 +6,31 @@ import { getReferenceSolution } from './referenceSolutions'; const getReferenceSolutionEvaluations = state => state.referenceSolutionEvaluations; const getResources = referenceSolutionEvaluations => referenceSolutionEvaluations.get('resources'); -export const referenceSolutionEvaluationsSelector = createSelector( - getReferenceSolutionEvaluations, - getResources -); +export const referenceSolutionEvaluationsSelector = createSelector(getReferenceSolutionEvaluations, getResources); export const referenceSolutionEvaluationSelector = evaluationId => - createSelector( - referenceSolutionEvaluationsSelector, - referenceSolutionEvaluations => referenceSolutionEvaluations.get(evaluationId) + createSelector(referenceSolutionEvaluationsSelector, referenceSolutionEvaluations => + referenceSolutionEvaluations.get(evaluationId) ); export const getReferenceSolutionEvaluationsByIdsSelector = ids => - createSelector( - referenceSolutionEvaluationsSelector, - evaluations => evaluations.filter(isReady).filter(evaluation => ids.indexOf(evaluation.getIn(['data', 'id'])) >= 0) + createSelector(referenceSolutionEvaluationsSelector, evaluations => + evaluations.filter(isReady).filter(evaluation => ids.indexOf(evaluation.getIn(['data', 'id'])) >= 0) ); -export const evaluationsForReferenceSolutionSelector = solutionId => - createSelector( - [getReferenceSolution(solutionId), referenceSolutionEvaluationsSelector], - (solution, evaluations) => - evaluations.filter(isReady).filter( - evaluation => - solution && - solution.getIn(['data', 'submissions']) && - solution - .get('data') - .get('submissions') - .indexOf(evaluation.getIn(['data', 'id'])) >= 0 - ) - ); +export const evaluationsForReferenceSolutionSelector = createSelector( + [getReferenceSolution, referenceSolutionEvaluationsSelector], + (solution, evaluations) => + evaluations.filter(isReady).filter( + evaluation => + solution && + solution.getIn(['data', 'submissions']) && + solution + .get('data') + .get('submissions') + .indexOf(evaluation.getIn(['data', 'id'])) >= 0 + ) +); export const fetchManyStatus = id => - createSelector( - getReferenceSolutionEvaluations, - state => state.getIn(['fetchManyStatus', fetchManyEndpoint(id)]) - ); + createSelector(getReferenceSolutionEvaluations, state => state.getIn(['fetchManyStatus', fetchManyEndpoint(id)])); diff --git a/src/redux/selectors/referenceSolutions.js b/src/redux/selectors/referenceSolutions.js index 3c81954c2..4d12c14c9 100644 --- a/src/redux/selectors/referenceSolutions.js +++ b/src/redux/selectors/referenceSolutions.js @@ -7,7 +7,9 @@ const getResources = referenceSolutions => referenceSolutions.get('resources'); export const allReferenceSolutionsSelector = createSelector(getReferenceSolutions, getResources); -export const getReferenceSolution = id => createSelector(allReferenceSolutionsSelector, solutions => solutions.get(id)); +export const getReferenceSolution = createSelector([allReferenceSolutionsSelector, getParam], (solutions, id) => + solutions.get(id) +); export const referenceSolutionsSelector = exerciseId => createSelector(allReferenceSolutionsSelector, referenceSolutions => {