33 * See the LICENSE file in the repository root folder for details.
44 */
55
6- import { Box , Link } from '@mui/material' ;
7- import Typography from '@mui/material/Typography' ;
6+ import { Box , Link , Stack , Typography } from '@mui/material' ;
87import { ImplementedChange } from 'shared' ;
9- import { fullNamePipe , datePipe } from '../utils/pipes' ;
8+ import { datePipe , fullNamePipe } from '../utils/pipes' ;
109import { Link as RouterLink } from 'react-router-dom' ;
1110import { routes } from '../utils/routes' ;
1211import DynamicTooltip from './DynamicTooltip' ;
@@ -15,28 +14,60 @@ interface ChangesListProps {
1514 changes : ImplementedChange [ ] ;
1615}
1716
17+ const URL_REGEX = / ( h t t p s ? : \/ \/ \S + ) / g;
18+
19+ const renderDetailWithLinks = ( detail : string ) =>
20+ detail . split ( URL_REGEX ) . map ( ( segment , idx ) => {
21+ if ( ! / ^ h t t p s ? : \/ \/ / . test ( segment ) ) return segment ;
22+ const trailing = segment . match ( / [ . , ; : ! ? ) \] " ' ` ] + $ / ) ?. [ 0 ] ?? '' ;
23+ const url = trailing ? segment . slice ( 0 , - trailing . length ) : segment ;
24+ return (
25+ < span key = { idx } >
26+ < Link href = { url } target = "_blank" rel = "noopener noreferrer" underline = "hover" >
27+ { url }
28+ </ Link >
29+ { trailing }
30+ </ span >
31+ ) ;
32+ } ) ;
33+
1834const ChangesList : React . FC < ChangesListProps > = ( { changes } ) => {
1935 return (
20- < Box >
21- < ul style = { { paddingLeft : '5px' , marginBottom : '0em' , listStyleType : 'none' } } >
22- { changes . map ( ( ic , idx ) => (
23- < li key = { idx } >
24- < Box style = { { display : 'flex' , flexDirection : 'row' } } >
25- < div style = { { marginRight : '4px' } } >
26- [
27- < Link component = { RouterLink } to = { `${ routes . CHANGE_REQUESTS } /${ ic . changeRequestId } ` } >
28- #{ ic . changeRequestIdentifier }
29- </ Link >
30- ]
31- </ div >
32- < DynamicTooltip title = { `${ fullNamePipe ( ic . implementer ) } - ${ datePipe ( ic . dateImplemented ) } ` } >
33- < Typography component = "span" > { ic . detail } </ Typography >
34- </ DynamicTooltip >
35- </ Box >
36- </ li >
37- ) ) }
38- </ ul >
39- </ Box >
36+ < Stack component = "ul" spacing = { 0.75 } sx = { { p : 0 , m : 0 , listStyleType : 'none' } } >
37+ { changes . map ( ( ic , idx ) => (
38+ < Box
39+ component = "li"
40+ key = { idx }
41+ sx = { {
42+ display : 'flex' ,
43+ flexDirection : { xs : 'column' , sm : 'row' } ,
44+ alignItems : { sm : 'baseline' } ,
45+ gap : 1 ,
46+ px : 1.25 ,
47+ py : 0.75 ,
48+ borderRadius : 1 ,
49+ backgroundColor : ( theme ) => theme . palette . action . hover
50+ } }
51+ >
52+ < Link
53+ component = { RouterLink }
54+ to = { `${ routes . CHANGE_REQUESTS } /${ ic . changeRequestId } ` }
55+ underline = "hover"
56+ sx = { { fontWeight : 600 , flexShrink : 0 } }
57+ >
58+ #{ ic . changeRequestIdentifier }
59+ </ Link >
60+ < DynamicTooltip title = { fullNamePipe ( ic . implementer ) } >
61+ < Typography component = "span" sx = { { flexGrow : 1 , wordBreak : 'break-word' } } >
62+ { renderDetailWithLinks ( ic . detail ) }
63+ </ Typography >
64+ </ DynamicTooltip >
65+ < Typography variant = "caption" sx = { { color : 'text.secondary' , whiteSpace : 'nowrap' , flexShrink : 0 } } >
66+ { datePipe ( ic . dateImplemented ) }
67+ </ Typography >
68+ </ Box >
69+ ) ) }
70+ </ Stack >
4071 ) ;
4172} ;
4273
0 commit comments