@@ -8,10 +8,14 @@ import {
88import { ParticipantData } from '../../../storage/types' ;
99import { SingleTaskLabelLines } from './SingleTaskLabelLines' ;
1010import { SingleTask } from './SingleTask' ;
11- import { StoredAnswer , StudyConfig } from '../../../parser/types' ;
11+ import { StudyConfig } from '../../../parser/types' ;
1212import { getComponentAnswerStatus } from '../../../utils/correctAnswer' ;
1313import { parseConditionParam } from '../../../utils/handleConditionLogic' ;
1414import { studyComponentToIndividualComponent } from '../../../utils/handleComponentInheritance' ;
15+ import {
16+ compareReplayAnswerEntries ,
17+ orderedReplayAnswerEntries ,
18+ } from './taskOrdering' ;
1519
1620const LABEL_GAP = 25 ;
1721const CHARACTER_SIZE = 8 ;
@@ -20,12 +24,6 @@ const margin = {
2024 left : 20 , top : 20 , right : 20 , bottom : 20 ,
2125} ;
2226
23- const sortedTaskNames = ( a : [ string , StoredAnswer ] , b : [ string , StoredAnswer ] ) => {
24- const splitA = a [ 1 ] . trialOrder . split ( '_' ) ;
25- const splitB = b [ 1 ] . trialOrder . split ( '_' ) ;
26- return splitA [ 0 ] === splitB [ 0 ] ? + splitA [ 1 ] - + splitB [ 1 ] : + splitA [ 0 ] - + splitB [ 0 ] ;
27- } ;
28-
2927export function AllTasksTimeline ( {
3028 participantData, width, studyId, studyConfig, maxLength,
3129} : { participantData : ParticipantData , width : number , studyId : string , studyConfig : StudyConfig | undefined , maxLength : number | undefined } ) {
@@ -54,20 +52,25 @@ export function AllTasksTimeline({
5452 } , [ participantData . answers , percentComplete , width ] ) ;
5553
5654 const maxHeight = useMemo ( ( ) => {
57- // Sort the entires by start time and filter out entries without start time
58- const sortedEntries = Object . entries ( participantData . answers || { } ) . filter ( ( answer ) => ! ! ( answer [ 1 ] . startTime ) ) . sort ( ( a , b ) => a [ 1 ] . startTime - b [ 1 ] . startTime ) ;
55+ const incompleteEntries = Object . entries ( participantData . answers || { } ) . filter ( ( e ) => e [ 1 ] . startTime === 0 ) . sort ( compareReplayAnswerEntries ) ;
56+ const incompleteEntryIndexes = new Map ( incompleteEntries . map ( ( [ identifier ] , index ) => [ identifier , index ] ) ) ;
57+ const sortedEntries = orderedReplayAnswerEntries ( participantData . answers ) ;
5958
6059 let currentHeight = 0 ;
6160 let _maxHeight = 0 ;
6261
6362 sortedEntries . forEach ( ( entry , i ) => {
64- const [ _name , answer ] = entry ;
63+ const [ identifier , answer ] = entry ;
6564
6665 // Check if the previous entry overlaps with the current entry
6766 const prev = i > 0 ? sortedEntries [ i - currentHeight - 1 ] : null ;
67+ const prevScale = prev && prev [ 1 ] . startTime ? xScale : incompleteXScale ;
68+ const prevStart = prev ? prev [ 1 ] . startTime ? prev [ 1 ] . startTime : incompleteEntryIndexes . get ( prev [ 0 ] ) ?? 0 : 0 ;
69+ const scale = answer . startTime === 0 ? incompleteXScale : xScale ;
70+ const scaleStart = answer . startTime ? answer . startTime : incompleteEntryIndexes . get ( identifier ) ?? 0 ;
6871
6972 // If the previous entry overlaps with the current entry , increase the height
70- if ( prev && prev [ 0 ] . length * ( CHARACTER_SIZE + 1 ) + xScale ( prev [ 1 ] . startTime ) > xScale ( answer . startTime ) ) {
73+ if ( prev && prev [ 0 ] . length * ( CHARACTER_SIZE + 1 ) + prevScale ( prevStart ) > scale ( scaleStart ) ) {
7174 currentHeight += 1 ;
7275 } else {
7376 currentHeight = 0 ;
@@ -79,7 +82,7 @@ export function AllTasksTimeline({
7982 } ) ;
8083
8184 return ( _maxHeight + 1 ) * LABEL_GAP + margin . top + margin . bottom ;
82- } , [ participantData . answers , xScale ] ) ;
85+ } , [ incompleteXScale , participantData . answers , xScale ] ) ;
8386
8487 const conditionParam = useMemo ( ( ) => {
8588 const parsedConditions = parseConditionParam ( participantData . conditions ?? participantData . searchParams ?. condition ) ;
@@ -90,11 +93,9 @@ export function AllTasksTimeline({
9093 const tasks : { identifier : string , line : JSX . Element , label : JSX . Element } [ ] = useMemo ( ( ) => {
9194 let currentHeight = 0 ;
9295
93- const incompleteEntries = Object . entries ( participantData . answers || { } ) . filter ( ( e ) => e [ 1 ] . startTime === 0 ) . sort ( sortedTaskNames ) ;
94-
95- const sortedEntries = Object . entries ( participantData . answers || { } ) . filter ( ( answer ) => ! ! ( answer [ 1 ] . startTime ) ) . sort ( ( a , b ) => a [ 1 ] . startTime - b [ 1 ] . startTime ) ;
96-
97- const combined = [ ...sortedEntries , ...incompleteEntries ] ;
96+ const incompleteEntries = Object . entries ( participantData . answers || { } ) . filter ( ( e ) => e [ 1 ] . startTime === 0 ) . sort ( compareReplayAnswerEntries ) ;
97+ const incompleteEntryIndexes = new Map ( incompleteEntries . map ( ( [ identifier ] , index ) => [ identifier , index ] ) ) ;
98+ const combined = orderedReplayAnswerEntries ( participantData . answers ) ;
9899
99100 const allElements = combined . map ( ( entry , i ) => {
100101 const scale = entry [ 1 ] . startTime === 0 ? incompleteXScale : xScale ;
@@ -104,9 +105,10 @@ export function AllTasksTimeline({
104105 const prev = i > 0 ? combined [ i - currentHeight - 1 ] : null ;
105106
106107 const prevScale = prev && prev [ 1 ] . startTime ? xScale : incompleteXScale ;
107- const prevStart = prev ? prev [ 1 ] . startTime ? prev [ 1 ] . startTime : incompleteEntries . indexOf ( prev ) : 0 ;
108- const scaleStart = answer . startTime ? answer . startTime : incompleteEntries . indexOf ( entry ) ;
109- const scaleEnd = answer . endTime > 0 ? answer . endTime : incompleteEntries . indexOf ( entry ) + 1 ;
108+ const prevStart = prev ? prev [ 1 ] . startTime ? prev [ 1 ] . startTime : incompleteEntryIndexes . get ( prev [ 0 ] ) ?? 0 : 0 ;
109+ const incompleteEntryIndex = incompleteEntryIndexes . get ( identifier ) ?? 0 ;
110+ const scaleStart = answer . startTime ? answer . startTime : incompleteEntryIndex ;
111+ const scaleEnd = answer . endTime > 0 ? answer . endTime : incompleteEntryIndex + 1 ;
110112
111113 if ( prev && prev [ 0 ] . length * ( CHARACTER_SIZE + 1 ) + prevScale ( prevStart ) > scale ( scaleStart ) ) {
112114 currentHeight += 1 ;
0 commit comments