@@ -540,25 +540,44 @@ function setupTimeline(timelineEvents: TimelineEventData[], notes: MergeRequestN
540
540
541
541
type calcTimelineArgs = {
542
542
authorExternalId : extract . MergeRequest [ 'authorExternalId' ] ,
543
+ createdAt : extract . MergeRequest [ 'createdAt' ] | null ,
543
544
}
544
545
545
- export function calculateTimeline ( timelineMapKeys : TimelineMapKey [ ] , timelineMap : Map < TimelineMapKey , MergeRequestNoteData | TimelineEventData > , { authorExternalId } : calcTimelineArgs ) {
546
-
547
- const committedEvents = timelineMapKeys . filter ( key => key . type === 'committed' ) ;
548
- committedEvents . sort ( ( a , b ) => a . timestamp . getTime ( ) - b . timestamp . getTime ( ) ) ;
549
546
550
- const firstCommitEvent = committedEvents [ 0 ] || null ;
551
- const lastCommitEvent = committedEvents [ committedEvents . length - 1 ] || null ;
547
+ function getStartedCodingAt ( timelineMapKeys : TimelineMapKey [ ] , createdAt : Date | null ) {
548
+ const firstCommitEvent = timelineMapKeys . find ( key => key . type === 'committed' ) ;
549
+
550
+ if ( ! firstCommitEvent ) return null ;
551
+
552
+ if ( ! createdAt ) {
553
+ return firstCommitEvent . timestamp ;
554
+ }
555
+
556
+ return firstCommitEvent . timestamp < createdAt ? firstCommitEvent . timestamp : createdAt ;
557
+ }
552
558
553
- const startedCodingAt = firstCommitEvent ? firstCommitEvent . timestamp : null ;
559
+ function getMergedAt ( timelineMapKeys : TimelineMapKey [ ] ) {
560
+ const firstMergedEvent = timelineMapKeys . find ( key => key . type === 'merged' ) ;
554
561
555
- const mergedEvents = timelineMapKeys . filter ( key => key . type === 'merged' ) ;
556
- mergedEvents . sort ( ( a , b ) => a . timestamp . getTime ( ) - b . timestamp . getTime ( ) ) ;
562
+ if ( firstMergedEvent ) {
563
+ return firstMergedEvent . timestamp ;
564
+ }
565
+
566
+ return null ;
567
+ }
568
+
569
+ export function calculateTimeline ( timelineMapKeys : TimelineMapKey [ ] , timelineMap : Map < TimelineMapKey , MergeRequestNoteData | TimelineEventData > , { authorExternalId, createdAt } : calcTimelineArgs ) {
570
+
571
+ const sortedTimelineMapKeys = [ ...timelineMapKeys ]
572
+ sortedTimelineMapKeys . sort ( ( a , b ) => a . timestamp . getTime ( ) - b . timestamp . getTime ( ) ) ;
573
+
574
+ const committedEvents = sortedTimelineMapKeys . filter ( key => key . type === 'committed' ) ;
575
+ const lastCommitEvent = committedEvents [ committedEvents . length - 1 ] || null ;
557
576
558
- const mergedAt = mergedEvents [ 0 ] ?. timestamp || null ;
577
+ const startedCodingAt = getStartedCodingAt ( committedEvents , createdAt ) ;
578
+ const mergedAt = getMergedAt ( sortedTimelineMapKeys ) ;
559
579
560
- const readyForReviewEvents = timelineMapKeys . filter ( key => key . type === 'ready_for_review' || key . type === 'review_requested' ) ;
561
- readyForReviewEvents . sort ( ( a , b ) => a . timestamp . getTime ( ) - b . timestamp . getTime ( ) ) ;
580
+ const readyForReviewEvents = sortedTimelineMapKeys . filter ( key => key . type === 'ready_for_review' || key . type === 'review_requested' ) ;
562
581
const lastReadyForReviewEvent = readyForReviewEvents [ readyForReviewEvents . length - 1 ] || null ;
563
582
564
583
const startedPickupAt = ( ( ) => {
@@ -567,8 +586,7 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
567
586
}
568
587
if ( lastReadyForReviewEvent === null && lastCommitEvent ) {
569
588
// problematic code: everything below is problematic
570
- const reviewedEventsBeforeLastCommitEvent = timelineMapKeys . filter ( key => key . type === 'reviewed' && key . timestamp < lastCommitEvent . timestamp ) ;
571
- reviewedEventsBeforeLastCommitEvent . sort ( ( a , b ) => a . timestamp . getTime ( ) - b . timestamp . getTime ( ) ) ;
589
+ const reviewedEventsBeforeLastCommitEvent = sortedTimelineMapKeys . filter ( key => key . type === 'reviewed' && key . timestamp < lastCommitEvent . timestamp ) ;
572
590
const firstReviewedEventBeforeLastCommitEvent = reviewedEventsBeforeLastCommitEvent [ 0 ] ;
573
591
if ( firstReviewedEventBeforeLastCommitEvent ) {
574
592
return [ ...committedEvents ] . reverse ( ) . find ( event => event . timestamp < firstReviewedEventBeforeLastCommitEvent . timestamp ) ?. timestamp || null ;
@@ -578,13 +596,12 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
578
596
}
579
597
if ( lastReadyForReviewEvent && lastCommitEvent ) {
580
598
// problematic code: there could be a commit between last commit and lastReadyForReviewEvent
581
- const reviewedEventsAfterLastReadyForReviewEvent = timelineMapKeys . filter (
599
+ const reviewedEventsAfterLastReadyForReviewEvent = sortedTimelineMapKeys . filter (
582
600
key =>
583
601
key . type === 'reviewed'
584
602
&& key . timestamp > lastReadyForReviewEvent . timestamp
585
603
&& key . timestamp < lastCommitEvent . timestamp
586
604
) ;
587
- reviewedEventsAfterLastReadyForReviewEvent . sort ( ( a , b ) => a . timestamp . getTime ( ) - b . timestamp . getTime ( ) ) ;
588
605
const firstReviewedEventAfterLastReadyForReviewEvent = reviewedEventsAfterLastReadyForReviewEvent [ 0 ]
589
606
590
607
if ( firstReviewedEventAfterLastReadyForReviewEvent ) {
@@ -617,6 +634,7 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
617
634
continue ;
618
635
}
619
636
637
+ // Edge-case: what if note is before first review event ?
620
638
const afterStartedPickupAt = startedPickupAt ? noteEvent . timestamp > startedPickupAt : true ;
621
639
const beforeMergedEvent = mergedAt ? noteEvent . timestamp < mergedAt : true ;
622
640
const isAuthorReviewer = eventData . authorExternalId === authorExternalId ;
@@ -674,6 +692,7 @@ function runTimeline(mergeRequestData: MergeRequestData, timelineEvents: Timelin
674
692
timelineMapKeys ,
675
693
timelineMap ,
676
694
{
695
+ createdAt : mergeRequestData . openedAt ,
677
696
authorExternalId : mergeRequestData . authorExternalId ,
678
697
} ) ;
679
698
0 commit comments