@@ -3,112 +3,114 @@ import { Link as LinkIcon } from '@openedx/paragon/icons';
3
3
import * as React from 'react' ;
4
4
import { useEffect , useState } from 'react' ;
5
5
import { useParams } from 'react-router-dom' ;
6
- import { Block , BlockMap , UsageId , useBlockData , usePanels , } from '../hooks' ;
6
+ import {
7
+ Block , BlockMap , UsageId , useBlockData , usePanels ,
8
+ } from '../hooks' ;
7
9
import { BlockCollapsible } from './BlockCollapsible' ;
8
10
import { HighlightMatch } from './HighlightMatch' ;
9
- import { PrintSyllabus } from " ./PrintSyllabus" ;
11
+ import { PrintSyllabus } from ' ./PrintSyllabus' ;
10
12
11
13
const filteredBlocks = (
12
- rootId : UsageId | undefined ,
13
- blocks : BlockMap | null ,
14
- query : string | null ,
14
+ rootId : UsageId | undefined ,
15
+ blocks : BlockMap | null ,
16
+ query : string | null ,
15
17
) : Set < UsageId > | null => {
16
- if ( ! query || ! blocks || ! rootId ) {
17
- return null ;
18
- }
19
- const matches = new Set < UsageId > ( ) ;
18
+ if ( ! query || ! blocks || ! rootId ) {
19
+ return null ;
20
+ }
21
+ const matches = new Set < UsageId > ( ) ;
20
22
21
- function filterBlocks ( blockId : UsageId ) {
22
- const block = blocks [ blockId ] ;
23
- if ( ! block ) {
24
- return false ;
25
- }
26
- let foundMatch = false ;
27
- if ( block . display_name . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) ) {
28
- matches . add ( blockId ) ;
29
- foundMatch = true ;
30
- }
31
- if ( block . children ) {
32
- const childMatch = block . children . filter ( filterBlocks ) ;
33
- if ( childMatch . length > 0 ) {
34
- matches . add ( blockId ) ;
35
- foundMatch = true ;
36
- }
37
- }
38
- return foundMatch ;
23
+ function filterBlocks ( blockId : UsageId ) {
24
+ const block = blocks [ blockId ] ;
25
+ if ( ! block ) {
26
+ return false ;
27
+ }
28
+ let foundMatch = false ;
29
+ if ( block . display_name . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) ) {
30
+ matches . add ( blockId ) ;
31
+ foundMatch = true ;
32
+ }
33
+ if ( block . children ) {
34
+ const childMatch = block . children . filter ( filterBlocks ) ;
35
+ if ( childMatch . length > 0 ) {
36
+ matches . add ( blockId ) ;
37
+ foundMatch = true ;
38
+ }
39
39
}
40
+ return foundMatch ;
41
+ }
40
42
41
- filterBlocks ( rootId ) ;
43
+ filterBlocks ( rootId ) ;
42
44
43
- return matches ;
45
+ return matches ;
44
46
} ;
45
47
export const Syllabus = ( ) => {
46
- const { courseId} = useParams ( ) ;
47
- const blockData = useBlockData ( courseId ) ;
48
- const blocks = blockData ?. blocks ;
49
- const rootBlock = blockData ?. blocks [ blockData . root ] ;
50
- const {
51
- isPanelOpen, toggleAll, togglePanel, allOpen, setOpenPanels,
52
- } = usePanels ( ) ;
53
- useEffect ( ( ) => {
54
- if ( blocks ) {
55
- setOpenPanels ( Object . fromEntries ( Object . keys ( blocks ) . map ( blockId => [ blockId , false ] ) ) ) ;
56
- }
57
- } , [ blocks , setOpenPanels ] ) ;
58
- const [ query , setQuery ] = useState ( '' ) ;
59
- if ( ! blockData || ! blocks || ! rootBlock ) {
60
- return null ;
48
+ const { courseId } = useParams ( ) ;
49
+ const blockData = useBlockData ( courseId ) ;
50
+ const blocks = blockData ?. blocks ;
51
+ const rootBlock = blockData ?. blocks [ blockData . root ] ;
52
+ const {
53
+ isPanelOpen, toggleAll, togglePanel, allOpen, setOpenPanels,
54
+ } = usePanels ( ) ;
55
+ useEffect ( ( ) => {
56
+ if ( blocks ) {
57
+ setOpenPanels ( Object . fromEntries ( Object . keys ( blocks ) . map ( blockId => [ blockId , false ] ) ) ) ;
61
58
}
62
- const matches = filteredBlocks ( blockData ?. root , blocks , query ) ;
63
- const iterMatches = (
64
- block : Block ,
65
- children : ( blockId : UsageId ) => React . ReactNode ,
66
- border = false ,
67
- ) => (
68
- block ?. children ?. map ( ( blockId : UsageId ) => ( ! matches || matches . has ( blockId ) ) && (
69
- < BlockCollapsible
70
- query = { query }
71
- block = { blockData . blocks [ blockId ] }
72
- key = { blockId }
73
- onToggle = { ( ) => togglePanel ( blockId ) }
74
- isOpen = { isPanelOpen ( blockId ) }
75
- border = { border }
76
- >
77
- { children ( blockId ) }
78
- </ BlockCollapsible >
79
- ) )
80
- ) ;
59
+ } , [ blocks , setOpenPanels ] ) ;
60
+ const [ query , setQuery ] = useState ( '' ) ;
61
+ if ( ! blockData || ! blocks || ! rootBlock ) {
62
+ return null ;
63
+ }
64
+ const matches = filteredBlocks ( blockData ?. root , blocks , query ) ;
65
+ const iterMatches = (
66
+ block : Block ,
67
+ children : ( blockId : UsageId ) => React . ReactNode ,
68
+ border = false ,
69
+ ) => (
70
+ block ?. children ?. map ( ( blockId : UsageId ) => ( ! matches || matches . has ( blockId ) ) && (
71
+ < BlockCollapsible
72
+ query = { query }
73
+ block = { blockData . blocks [ blockId ] }
74
+ key = { blockId }
75
+ onToggle = { ( ) => togglePanel ( blockId ) }
76
+ isOpen = { isPanelOpen ( blockId ) }
77
+ border = { border }
78
+ >
79
+ { children ( blockId ) }
80
+ </ BlockCollapsible >
81
+ ) )
82
+ ) ;
81
83
82
- return (
83
- < div >
84
- < div className = "d-flex justify-content-end mb-2" >
85
- < SearchField value = { query } onChange = { setQuery } onSubmit = { setQuery } />
86
- < Button variant = "outline-primary" size = "sm" onClick = { ( ) => toggleAll ( ) } >
87
- { allOpen
88
- ? 'Collapse all'
89
- : 'Expand all' }
90
- </ Button >
91
- </ div >
92
- { rootBlock && iterMatches ( rootBlock , ( sectionId : UsageId ) => (
93
- iterMatches ( blocks [ sectionId ] , ( subsectionId : UsageId ) => (
94
- iterMatches ( blocks [ subsectionId ] , ( unitId : UsageId ) => (
95
- blocks [ unitId ] . children . flatMap ( ( blockId : UsageId ) => (
96
- blocks [ blockId ] ?. links ?. map ( link => (
97
- < div className = "d-flex flex-column" key = { blockId + link . href } >
98
- < a
99
- className = "d-flex ml-2 align-items-center"
100
- href = { link . href }
101
- >
102
- < Icon src = { LinkIcon } size = "xs" className = "mr-2" />
103
- < HighlightMatch query = { query } text = { link . text } />
104
- </ a >
105
- </ div >
106
- ) )
107
- ) ) . filter ( item => ! ! item )
108
- ) )
109
- ) )
110
- ) , true ) }
111
- { blockData && < PrintSyllabus blockData = { blockData } /> }
112
- </ div >
113
- ) ;
84
+ return (
85
+ < div >
86
+ < div className = "d-flex justify-content-end mb-2" >
87
+ < SearchField value = { query } onChange = { setQuery } onSubmit = { setQuery } />
88
+ < Button variant = "outline-primary" size = "sm" onClick = { ( ) => toggleAll ( ) } >
89
+ { allOpen
90
+ ? 'Collapse all'
91
+ : 'Expand all' }
92
+ </ Button >
93
+ </ div >
94
+ { rootBlock && iterMatches ( rootBlock , ( sectionId : UsageId ) => (
95
+ iterMatches ( blocks [ sectionId ] , ( subsectionId : UsageId ) => (
96
+ iterMatches ( blocks [ subsectionId ] , ( unitId : UsageId ) => (
97
+ blocks [ unitId ] . children . flatMap ( ( blockId : UsageId ) => (
98
+ blocks [ blockId ] ?. links ?. map ( link => (
99
+ < div className = "d-flex flex-column" key = { blockId + link . href } >
100
+ < a
101
+ className = "d-flex ml-2 align-items-center"
102
+ href = { link . href }
103
+ >
104
+ < Icon src = { LinkIcon } size = "xs" className = "mr-2" />
105
+ < HighlightMatch query = { query } text = { link . text } />
106
+ </ a >
107
+ </ div >
108
+ ) )
109
+ ) ) . filter ( item => ! ! item )
110
+ ) )
111
+ ) )
112
+ ) , true ) }
113
+ { blockData && < PrintSyllabus blockData = { blockData } /> }
114
+ </ div >
115
+ ) ;
114
116
} ;
0 commit comments