@@ -2,11 +2,12 @@ import { LoadingButton } from '@atlaskit/button';
2
2
import Page , { Grid , GridColumn } from '@atlaskit/page' ;
3
3
import Tooltip from '@atlaskit/tooltip' ;
4
4
import WidthDetector from '@atlaskit/width-detector' ;
5
- import { CommentVisibility , Transition } from '@atlassianlabs/jira-pi-common-models' ;
5
+ import { CommentVisibility , MinimalIssue , Transition } from '@atlassianlabs/jira-pi-common-models' ;
6
6
import { FieldUI , InputFieldUI , SelectFieldUI , UIType , ValueType } from '@atlassianlabs/jira-pi-meta-models' ;
7
7
import { Box } from '@material-ui/core' ;
8
8
import { formatDistanceToNow , parseISO } from 'date-fns' ;
9
9
import * as React from 'react' ;
10
+ import { DetailedSiteInfo } from 'src/atlclients/authInfo' ;
10
11
import { v4 } from 'uuid' ;
11
12
12
13
import { AnalyticsView } from '../../../../analyticsTypes' ;
@@ -42,6 +43,8 @@ export interface ViewState extends CommonEditorViewState, EditIssueData {
42
43
currentInlineDialog : string ;
43
44
commentText : string ;
44
45
isEditingComment : boolean ;
46
+ hierarchyLoading : boolean ;
47
+ hierarchy : MinimalIssue < DetailedSiteInfo > [ ] ;
45
48
}
46
49
47
50
const emptyState : ViewState = {
@@ -51,6 +54,8 @@ const emptyState: ViewState = {
51
54
currentInlineDialog : '' ,
52
55
commentText : '' ,
53
56
isEditingComment : false ,
57
+ hierarchyLoading : false ,
58
+ hierarchy : [ ] ,
54
59
} ;
55
60
56
61
export default class JiraIssuePage extends AbstractIssueEditorPage < Emit , Accept , { } , ViewState > {
@@ -116,6 +121,14 @@ export default class JiraIssuePage extends AbstractIssueEditorPage<Emit, Accept,
116
121
}
117
122
break ;
118
123
}
124
+ case 'hierarchyUpdate' : {
125
+ this . setState ( { hierarchy : e . hierarchy , hierarchyLoading : false } ) ;
126
+ break ;
127
+ }
128
+ case 'hierarchyLoading' : {
129
+ this . setState ( { hierarchy : e . hierarchy , hierarchyLoading : true } ) ;
130
+ break ;
131
+ }
119
132
}
120
133
}
121
134
return handled ;
@@ -472,22 +485,8 @@ export default class JiraIssuePage extends AbstractIssueEditorPage<Emit, Accept,
472
485
} ;
473
486
474
487
getMainPanelNavMarkup ( ) : any {
475
- const epicLinkValue = this . state . fieldValues [ this . state . epicFieldInfo . epicLink . id ] ;
476
- let epicLinkKey : string = '' ;
477
-
478
- if ( epicLinkValue ) {
479
- if ( typeof epicLinkValue === 'object' && epicLinkValue . value ) {
480
- epicLinkKey = epicLinkValue . value ;
481
- } else if ( typeof epicLinkValue === 'string' ) {
482
- epicLinkKey = epicLinkValue ;
483
- }
484
- }
485
-
486
- const parentIconUrl =
487
- this . state . fieldValues [ 'parent' ] && this . state . fieldValues [ 'parent' ] . issuetype
488
- ? this . state . fieldValues [ 'parent' ] . issuetype . iconUrl
489
- : undefined ;
490
488
const itIconUrl = this . state . fieldValues [ 'issuetype' ] ? this . state . fieldValues [ 'issuetype' ] . iconUrl : undefined ;
489
+
491
490
return (
492
491
< div >
493
492
{ this . state . showPMF && (
@@ -501,45 +500,69 @@ export default class JiraIssuePage extends AbstractIssueEditorPage<Emit, Accept,
501
500
) }
502
501
< div className = "ac-page-header" >
503
502
< div className = "ac-breadcrumbs" >
504
- { epicLinkValue && epicLinkKey !== '' && (
505
- < React . Fragment >
506
- < NavItem
507
- text = { epicLinkKey }
508
- onItemClick = { ( ) =>
509
- this . handleOpenIssue ( { siteDetails : this . state . siteDetails , key : epicLinkKey } )
510
- }
511
- />
512
- < span className = "ac-breadcrumb-divider" > /</ span >
513
- </ React . Fragment >
514
- ) }
515
- { this . state . fieldValues [ 'parent' ] && (
516
- < React . Fragment >
517
- < NavItem
518
- text = { this . state . fieldValues [ 'parent' ] . key }
519
- iconUrl = { parentIconUrl }
520
- onItemClick = { ( ) =>
521
- this . handleOpenIssue ( {
522
- siteDetails : this . state . siteDetails ,
523
- key : this . state . fieldValues [ 'parent' ] . key ,
524
- } )
525
- }
526
- />
527
- < span className = "ac-breadcrumb-divider" > /</ span >
528
- </ React . Fragment >
503
+ { this . state . hierarchy && this . state . hierarchy . length > 0 && (
504
+ < >
505
+ { this . state . hierarchyLoading && this . state . hierarchy . length <= 1 && (
506
+ < >
507
+ < span className = "ac-breadcrumb-loading" >
508
+ { [ ...Array ( 3 ) ] . map ( ( _ , idx ) => (
509
+ < span
510
+ key = { idx }
511
+ className = "animate-pulse"
512
+ style = { { animationDelay : `${ idx * 0.2 } s` } }
513
+ >
514
+ .
515
+ </ span >
516
+ ) ) }
517
+ </ span >
518
+ < span className = "ac-breadcrumb-divider" > /</ span >
519
+ </ >
520
+ ) }
521
+ { this . state . hierarchy . map ( ( issue , index ) => {
522
+ const isLastItem = index === this . state . hierarchy . length - 1 ;
523
+ const shouldOpenInJira = issue . key === this . state . key ;
524
+ const handleItemClick = ! shouldOpenInJira
525
+ ? ( ) =>
526
+ this . handleOpenIssue ( {
527
+ siteDetails : this . state . siteDetails ,
528
+ key : issue . key ,
529
+ } )
530
+ : undefined ;
531
+
532
+ return (
533
+ < React . Fragment key = { issue . key } >
534
+ < NavItem
535
+ text = { issue . key }
536
+ iconUrl = { issue . issuetype ?. iconUrl }
537
+ href = {
538
+ shouldOpenInJira
539
+ ? `${ this . state . siteDetails . baseLinkUrl } /browse/${ issue . key } `
540
+ : undefined
541
+ }
542
+ onItemClick = { handleItemClick }
543
+ onCopy = { isLastItem ? this . handleCopyIssueLink : undefined }
544
+ />
545
+ { ! isLastItem && < span className = "ac-breadcrumb-divider" > /</ span > }
546
+ </ React . Fragment >
547
+ ) ;
548
+ } ) }
549
+ </ >
529
550
) }
530
-
531
- < Tooltip
532
- content = { `Created on ${
533
- this . state . fieldValues [ 'created.rendered' ] || this . state . fieldValues [ 'created' ]
534
- } `}
535
- >
536
- < NavItem
537
- text = { `${ this . state . key } ` }
538
- href = { `${ this . state . siteDetails . baseLinkUrl } /browse/${ this . state . key } ` }
539
- iconUrl = { itIconUrl }
540
- onCopy = { this . handleCopyIssueLink }
541
- />
542
- </ Tooltip >
551
+ { ! this . state . hierarchy ||
552
+ ( this . state . hierarchy . length === 0 && (
553
+ < Tooltip
554
+ content = { `Created on ${
555
+ this . state . fieldValues [ 'created.rendered' ] || this . state . fieldValues [ 'created' ]
556
+ } `}
557
+ >
558
+ < NavItem
559
+ text = { `${ this . state . key } ` }
560
+ href = { `${ this . state . siteDetails . baseLinkUrl } /browse/${ this . state . key } ` }
561
+ iconUrl = { itIconUrl }
562
+ onCopy = { this . handleCopyIssueLink }
563
+ />
564
+ </ Tooltip >
565
+ ) ) }
543
566
</ div >
544
567
</ div >
545
568
{ this . state . isErrorBannerOpen && (
@@ -624,6 +647,7 @@ export default class JiraIssuePage extends AbstractIssueEditorPage<Emit, Accept,
624
647
</ div >
625
648
) ;
626
649
}
650
+
627
651
commonSidebar ( ) : any {
628
652
const commonItems : SidebarItem [ ] = [ 'assignee' , 'reporter' , 'labels' , 'priority' , 'components' , 'fixVersions' ]
629
653
. filter ( ( field ) => ! ! this . state . fields [ field ] )
0 commit comments