@@ -63,14 +63,15 @@ import {
6363 fetchManyAssignmentSolutionsStatus ,
6464 isAssignmentSolversLoading ,
6565 getAssignmentSolverSelector ,
66+ getOneAssignmentSolvers ,
6667} from '../../redux/selectors/solutions' ;
6768import { isReady , getJsData , getId } from '../../redux/helpers/resourceManager' ;
6869
6970import { storageGetItem , storageSetItem } from '../../helpers/localStorage' ;
7071import withLinks from '../../helpers/withLinks' ;
7172import { safeGet , identity , arrayToObject , toPlainAscii , hasPermissions } from '../../helpers/common' ;
7273
73- const prepareTableColumnDescriptors = defaultMemoize ( ( loggedUserId , assignmentId , groupId , locale , links ) => {
74+ const prepareTableColumnDescriptors = defaultMemoize ( ( loggedUserId , assignmentId , groupId , onlyBest , locale , links ) => {
7475 const { SOLUTION_DETAIL_URI_FACTORY , SOLUTION_SOURCE_CODES_URI_FACTORY , GROUP_USER_SOLUTIONS_URI_FACTORY } = links ;
7576 const nameComparator = createUserNameComparator ( locale ) ;
7677
@@ -103,6 +104,34 @@ const prepareTableColumnDescriptors = defaultMemoize((loggedUserId, assignmentId
103104 }
104105 ) ,
105106
107+ new SortableTableColumnDescriptor ( 'attempt' , '#' , {
108+ className : 'text-center' ,
109+ cellRenderer : ( { attemptIndex, lastAttemptIndex } ) => (
110+ < small
111+ className = {
112+ 'text-nowrap' +
113+ ( onlyBest && lastAttemptIndex && lastAttemptIndex !== attemptIndex
114+ ? ' text-bold text-warning'
115+ : ' text-muted' )
116+ } >
117+ { ! lastAttemptIndex ? (
118+ < LoadingIcon />
119+ ) : onlyBest && lastAttemptIndex && lastAttemptIndex === attemptIndex ? (
120+ attemptIndex
121+ ) : (
122+ < FormattedMessage
123+ id = "app.solution.solutionAttemptValue"
124+ defaultMessage = "{index} of {count}"
125+ values = { {
126+ index : attemptIndex ,
127+ count : lastAttemptIndex ,
128+ } }
129+ />
130+ ) }
131+ </ small >
132+ ) ,
133+ } ) ,
134+
106135 new SortableTableColumnDescriptor ( 'user' , < FormattedMessage id = "generic.nameOfPerson" defaultMessage = "Name" /> , {
107136 className : 'text-left' ,
108137 comparator : ( { user : u1 , date : d1 } , { user : u2 , date : d2 } ) => nameComparator ( u1 , u2 ) || d2 - d1 , // dates are implicitly in reversed order
@@ -209,11 +238,12 @@ const prepareTableColumnDescriptors = defaultMemoize((loggedUserId, assignmentId
209238 } ) ,
210239 ] ;
211240
212- return columns ;
241+ return columns . filter ( c => c ) ;
213242} ) ;
214243
215244const prepareTableData = defaultMemoize (
216- ( assignmentSolutions , users , runtimeEnvironments , onlyBestSolutionsCheckbox ) => {
245+ ( assignmentSolutions , users , assignmentSolvers , runtimeEnvironments , onlyBestSolutionsCheckbox ) => {
246+ const solvers = ( assignmentSolvers && assignmentSolvers . toJS ( ) ) || { } ;
217247 const usersIndex = arrayToObject ( users ) ;
218248 return assignmentSolutions
219249 . toArray ( )
@@ -226,6 +256,7 @@ const prepareTableData = defaultMemoize(
226256 lastSubmission,
227257 authorId,
228258 createdAt,
259+ attemptIndex,
229260 runtimeEnvironmentId,
230261 note,
231262 maxPoints,
@@ -245,6 +276,7 @@ const prepareTableData = defaultMemoize(
245276 icon : { id, commentsStats, lastSubmission, accepted, review, permissionHints, isBestSolution, plagiarism } ,
246277 user : usersIndex [ authorId ] ,
247278 date : createdAt ,
279+ attempt : { attemptIndex, lastAttemptIndex : solvers [ authorId ] && solvers [ authorId ] . lastAttemptIndex } ,
248280 validity : statusEvaluated ? safeGet ( lastSubmission , [ 'evaluation' , 'score' ] ) : null ,
249281 points : statusEvaluated ? { maxPoints, bonusPoints, actualPoints } : { actualPoints : null } ,
250282 runtimeEnvironment : runtimeEnvironments . find ( ( { id } ) => id === runtimeEnvironmentId ) ,
@@ -354,6 +386,7 @@ class AssignmentStats extends Component {
354386 fetchManyStatus,
355387 assignmentSolversLoading,
356388 assignmentSolverSelector,
389+ assignmentSolvers,
357390 intl : { locale } ,
358391 links,
359392 } = this . props ;
@@ -550,11 +583,19 @@ class AssignmentStats extends Component {
550583 noPadding >
551584 < SortableTable
552585 hover
553- columns = { prepareTableColumnDescriptors ( loggedUserId , assignmentId , group . id , locale , links ) }
586+ columns = { prepareTableColumnDescriptors (
587+ loggedUserId ,
588+ assignmentId ,
589+ group . id ,
590+ this . state . onlyBestSolutionsCheckbox ,
591+ locale ,
592+ links
593+ ) }
554594 defaultOrder = "date"
555595 data = { prepareTableData (
556596 assignmentSolutions ,
557597 getStudents ( group . id ) ,
598+ assignmentSolversLoading ? null : assignmentSolvers ,
558599 runtimes ,
559600 this . state . onlyBestSolutionsCheckbox
560601 ) }
@@ -595,6 +636,7 @@ AssignmentStats.propTypes = {
595636 fetchManyStatus : PropTypes . string ,
596637 assignmentSolversLoading : PropTypes . bool ,
597638 assignmentSolverSelector : PropTypes . func . isRequired ,
639+ assignmentSolvers : ImmutablePropTypes . map ,
598640 closeReview : PropTypes . func . isRequired ,
599641 intl : PropTypes . object ,
600642 links : PropTypes . object . isRequired ,
@@ -627,6 +669,7 @@ export default withLinks(
627669 fetchManyStatus : fetchManyAssignmentSolutionsStatus ( assignmentId ) ( state ) ,
628670 assignmentSolversLoading : isAssignmentSolversLoading ( state ) ,
629671 assignmentSolverSelector : getAssignmentSolverSelector ( state ) ,
672+ assignmentSolvers : getOneAssignmentSolvers ( state , assignmentId ) ,
630673 } ;
631674 } ,
632675 (
0 commit comments