11import {
2- Card , Icon , OverlayTrigger , Table , Tooltip ,
2+ Card , Icon , Table ,
33} from '@openedx/paragon' ;
44import {
5- OpenInNew , Lock , LinkOff , InfoOutline ,
5+ ArrowForwardIos ,
6+ LinkOff ,
67} from '@openedx/paragon/icons' ;
7- import { useIntl } from '@edx/frontend-platform/i18n' ;
88import { FC } from 'react' ;
9- import { Unit } from '../types' ;
9+ import { Filters , Unit } from '../types' ;
1010import messages from './messages' ;
11- import LockedInfoIcon from './LockedInfoIcon' ;
11+ import CustomIcon from './CustomIcon' ;
12+ import lockedIcon from './lockedIcon' ;
13+ import ManualIcon from './manualIcon' ;
1214
1315const BrokenLinkHref : FC < { href : string } > = ( { href } ) => {
1416 const handleClick = ( event : React . MouseEvent < HTMLAnchorElement > ) => {
@@ -25,150 +27,139 @@ const BrokenLinkHref: FC<{ href: string }> = ({ href }) => {
2527 ) ;
2628} ;
2729
28- const GoToBlock : FC < { block : { url : string } } > = ( { block } ) => {
30+ const GoToBlock : FC < { block : { url : string , displayName : string } } > = ( { block } ) => {
2931 const handleClick = ( event : React . MouseEvent < HTMLAnchorElement > ) => {
3032 event . preventDefault ( ) ;
3133 window . open ( block . url , '_blank' ) ;
3234 } ;
3335
3436 return (
35- < span style = { { display : 'flex' , gap : '.5rem' } } >
36- < Icon src = { OpenInNew } />
37- < a href = { block . url } onClick = { handleClick } rel = "noreferrer" >
38- Go to Block
37+ < div className = "go-to-block-link-container" >
38+ < a href = { block . url } onClick = { handleClick } className = "broken-link" rel = "noreferrer" >
39+ { block . displayName }
3940 </ a >
40- </ span >
41+ </ div >
4142 ) ;
4243} ;
4344
44- const RecommendedManualCheckHeading = ( ) => {
45- const intl = useIntl ( ) ;
46- return (
47- < span className = "d-flex align-items-center font-weight-bold py-2" >
48- { intl . formatMessage ( messages . recommendedManualCheckText ) }
49- < OverlayTrigger
50- key = "top"
51- placement = "top"
52- overlay = { (
53- < Tooltip id = "tooltip-top" >
54- { intl . formatMessage ( messages . recommendedManualCheckTooltip ) }
55- </ Tooltip >
56- ) }
57- >
58- < Icon className = "ml-1 pl-1" src = { InfoOutline } />
59- </ OverlayTrigger >
60- </ span >
61- ) ;
62- } ;
45+ const LinksCol : FC < { block : { url : string , displayName : string } , href : string } > = ( { block, href } ) => (
46+ < span className = "links-container" >
47+ < GoToBlock block = { { url : block . url , displayName : block . displayName || 'Go to block' } } />
48+ < Icon className = "arrow-forward-ios" src = { ArrowForwardIos } />
49+ < BrokenLinkHref href = { href } />
50+ </ span >
51+ ) ;
6352
6453interface BrokenLinkTableProps {
6554 unit : Unit ;
66- showLockedLinks : boolean ;
55+ filters : Filters ;
6756}
6857
6958type TableData = {
70- blockLink : JSX . Element ;
71- brokenLink : JSX . Element ;
59+ Links : JSX . Element ;
7260 status : JSX . Element ;
7361} [ ] ;
7462
7563const BrokenLinkTable : FC < BrokenLinkTableProps > = ( {
7664 unit,
77- showLockedLinks,
78- } ) => {
79- const intl = useIntl ( ) ;
80- return (
81- < Card className = "unit-card rounded-sm pt-2 pl-3 pr-4 mb-2.5" >
82- < p className = "unit-header" > { unit . displayName } </ p >
83- < Table
84- data = { unit . blocks . reduce (
85- (
86- acc : TableData ,
87- block ,
88- ) => {
65+ filters,
66+ } ) => (
67+ < Card className = "unit-card rounded-sm pt-2 pl-3 pr-4 mb-2.5" >
68+ < p className = "unit-header" > { unit . displayName } </ p >
69+ < Table
70+ data = { unit . blocks . reduce (
71+ (
72+ acc : TableData ,
73+ block ,
74+ ) => {
75+ if (
76+ filters . brokenLinks
77+ || ( ! filters . brokenLinks && ! filters . externalForbiddenLinks && ! filters . lockedLinks )
78+ ) {
8979 const blockBrokenLinks = block . brokenLinks . map ( ( link ) => ( {
90- blockLink : < GoToBlock block = { block } /> ,
91- blockDisplayName : block . displayName || '' ,
92- brokenLink : < BrokenLinkHref href = { link } /> ,
80+ Links : (
81+ < LinksCol
82+ block = { { url : block . url , displayName : block . displayName || 'Go to block' } }
83+ href = { link }
84+ />
85+ ) ,
9386 status : (
94- < span className = "link-status-text" >
95- < Icon src = { LinkOff } className = "broken-link-icon" />
96- < span >
97- { intl . formatMessage ( messages . brokenLinkStatus ) }
98- </ span >
99- </ span >
87+ < CustomIcon
88+ icon = { LinkOff }
89+ message1 = { messages . brokenLabel }
90+ message2 = { messages . brokenInfoTooltip }
91+ />
10092 ) ,
10193 } ) ) ;
10294 acc . push ( ...blockBrokenLinks ) ;
95+ }
10396
104- if ( showLockedLinks ) {
105- const blockLockedLinks = block . lockedLinks . map ( ( link ) => ( {
106- blockLink : < GoToBlock block = { block } /> ,
107- blockDisplayName : block . displayName || '' ,
108- brokenLink : < BrokenLinkHref href = { link } /> ,
109- status : (
110- < span className = "link-status-text" >
111- < Icon src = { Lock } className = "lock-icon" />
112- { intl . formatMessage ( messages . lockedLinkStatus ) } { ' ' }
113- < LockedInfoIcon />
114- </ span >
115- ) ,
116- } ) ) ;
97+ if (
98+ filters . lockedLinks
99+ || ( ! filters . brokenLinks && ! filters . externalForbiddenLinks && ! filters . lockedLinks )
100+ ) {
101+ const blockLockedLinks = block . lockedLinks . map ( ( link ) => ( {
102+ Links : (
103+ < LinksCol
104+ block = { { url : block . url , displayName : block . displayName || 'Go to block' } }
105+ href = { link }
106+ />
107+ ) ,
108+ status : (
109+ < CustomIcon
110+ icon = { lockedIcon }
111+ message1 = { messages . lockedLabel }
112+ message2 = { messages . lockedInfoTooltip }
113+ />
114+ ) ,
115+ } ) ) ;
117116
118- acc . push ( ...blockLockedLinks ) ;
119- }
117+ acc . push ( ...blockLockedLinks ) ;
118+ }
120119
121- if ( block . externalForbiddenLinks ?. length > 0 ) {
122- const recommendedManualCheckHeading = {
123- blockLink : < div /> ,
124- blockDisplayName : < RecommendedManualCheckHeading /> ,
125- brokenLink : < div /> ,
126- status : < div /> ,
127- } ;
128- const externalForbiddenLinks = block . externalForbiddenLinks . map ( ( link ) => ( {
129- blockLink : < GoToBlock block = { block } /> ,
130- blockDisplayName : block . displayName || '' ,
131- brokenLink : < BrokenLinkHref href = { link } /> ,
132- status : < div /> ,
133- } ) ) ;
120+ if (
121+ filters . externalForbiddenLinks
122+ || ( ! filters . brokenLinks && ! filters . externalForbiddenLinks && ! filters . lockedLinks )
123+ ) {
124+ const externalForbiddenLinks = block . externalForbiddenLinks . map ( ( link ) => ( {
125+ Links : (
126+ < LinksCol
127+ block = { { url : block . url , displayName : block . displayName || 'Go to block' } }
128+ href = { link }
129+ />
130+ ) ,
131+ status : (
132+ < CustomIcon
133+ icon = { ManualIcon }
134+ message1 = { messages . manualLabel }
135+ message2 = { messages . manualInfoTooltip }
136+ />
137+ ) ,
138+ } ) ) ;
134139
135- acc . push ( recommendedManualCheckHeading ) ;
136- acc . push ( ...externalForbiddenLinks ) ;
137- }
140+ acc . push ( ...externalForbiddenLinks ) ;
141+ }
138142
139- return acc ;
140- } ,
141- [ ] ,
142- ) }
143- columns = { [
144- {
145- key : 'blockDisplayName' ,
146- columnSortable : false ,
147- width : 'col-3' ,
148- hideHeader : true ,
149- } ,
150- {
151- key : 'blockLink' ,
152- columnSortable : false ,
153- width : 'col-3' ,
154- hideHeader : true ,
155- } ,
156- {
157- key : 'brokenLink' ,
158- columnSortable : false ,
159- width : 'col-6' ,
160- hideHeader : true ,
161- } ,
162- {
163- key : 'status' ,
164- columnSortable : false ,
165- width : 'col-6' ,
166- hideHeader : true ,
167- } ,
168- ] }
169- />
170- </ Card >
171- ) ;
172- } ;
143+ return acc ;
144+ } ,
145+ [ ] ,
146+ ) }
147+ columns = { [
148+ {
149+ key : 'Links' ,
150+ columnSortable : false ,
151+ width : 'col-9' ,
152+ hideHeader : true ,
153+ } ,
154+ {
155+ key : 'status' ,
156+ columnSortable : false ,
157+ width : 'col-3' ,
158+ hideHeader : true ,
159+ } ,
160+ ] }
161+ />
162+ </ Card >
163+ ) ;
173164
174165export default BrokenLinkTable ;
0 commit comments