1- import { useEffect , useMemo , useState } from "react" ;
1+ import { useEffect , useMemo , useState , useCallback } from "react" ;
22import { ContentItem , ContentModel , Language , User } from "../services/types" ;
33import { BlockModel } from "../../shell/views/SearchPage/List/Block" ;
44import { AppState } from "shell/store/types" ;
5- import { useSelector } from "react-redux" ;
5+ import { useDispatch , useSelector } from "react-redux" ;
6+ import { fetchItems } from "shell/store/content" ;
67
78type UsersMap = Record < string , string > ;
9+
810type LanguageMap = Record < string , { code : string } > ;
911
12+ type SearchBlocksByKeywordProps = {
13+ isLoading : boolean ;
14+ } ;
15+
1016type SearchResult = {
1117 blocks : BlockModel [ ] ;
1218 setBlockKeyword : ( term : string ) => void ;
@@ -22,37 +28,32 @@ const toProperCase = (str?: string): string => {
2228 . trim ( ) ;
2329} ;
2430
25- export const useSearchBlocksByKeyword = (
26- contents ?: ContentItem [ ] ,
27- isLoading ?: boolean
28- ) : SearchResult => {
31+ const blockKeywords : string [ ] = [
32+ "block" ,
33+ "blocks" ,
34+ "block model" ,
35+ "block models" ,
36+ "blocks models" ,
37+ ] ;
38+
39+ export const useSearchBlocksByKeyword = ( {
40+ isLoading,
41+ } : SearchBlocksByKeywordProps ) : SearchResult => {
42+ const dispatch = useDispatch ( ) ;
2943 const [ searchTerm , setSearchTerm ] = useState ( "" ) ;
30- const [ blockVariants , setBlockVariants ] = useState ( [ ] ) ;
44+ const [ isFetchingVariants , setIsFetchingVariants ] = useState ( false ) ;
3145
32- const modelsRaw : ContentModel [ ] = useSelector (
33- ( state : AppState ) => state ?. models
34- ) ;
3546 const users : User [ ] = useSelector ( ( state : AppState ) => state ?. users ) ;
3647 const languages : Language [ ] = useSelector (
3748 ( state : AppState ) => state ?. languages
3849 ) ;
39-
40- const normalizedSearch = searchTerm . toLowerCase ( ) ?. trim ( ) ;
41-
42- const blockModels = useMemo < BlockModel [ ] > ( ( ) => {
43- if ( ! Object . values ( modelsRaw ) ?. length ) return [ ] ;
44- return Object . values ( modelsRaw )
45- ?. filter ( ( block : ContentModel ) => block ?. type === "block" )
46- . map ( ( block ) => block as unknown as BlockModel ) ;
47- } , [ modelsRaw ] ) ;
48-
49- const blockModelsMap = useMemo (
50- ( ) =>
51- ! ! blockModels ?. length &&
52- Object . fromEntries ( blockModels ?. map ( ( model ) => [ model ?. ZUID , model ] ) ) ,
53- [ blockModels ]
50+ const defaultLanguage = languages ?. find (
51+ ( lang : Language ) => lang ?. default && lang ?. active
5452 ) ;
5553
54+ const models = useSelector ( ( state : AppState ) => state ?. models ) ;
55+ const contents = useSelector ( ( state : AppState ) => state ?. content ) ;
56+
5657 const usersMap = useMemo < UsersMap > (
5758 ( ) =>
5859 ! ! users ?. length &&
@@ -72,96 +73,145 @@ export const useSearchBlocksByKeyword = (
7273 [ languages ]
7374 ) ;
7475
75- useEffect ( ( ) => {
76- if ( ! normalizedSearch ) return ;
77- const blockModelZUIDs = blockModels ?. map ( ( block ) => block ?. ZUID ) ;
78- const langIDs = Object . keys ( languageMap ) ;
79- const variants = ! contents ?. length
80- ? [ ]
81- : contents ?. filter (
82- ( content : ContentItem ) =>
83- blockModelZUIDs ?. includes ( content ?. meta ?. contentModelZUID ) &&
84- langIDs ?. includes ( String ( content ?. meta ?. langID ) )
85- ) ;
86- setBlockVariants ( variants ) ;
87- } , [ normalizedSearch , blockModels , languageMap , contents ] ) ;
76+ const normalizedSearchTerm = searchTerm . toLowerCase ( ) ?. trim ( ) ;
77+ const showAll = blockKeywords . includes ( normalizedSearchTerm ) ;
78+
79+ const blocks = useMemo < BlockModel [ ] > ( ( ) => {
80+ const modelsArray = models ? Object . values ( models ) : [ ] ;
81+ if ( ! modelsArray ?. length ) return [ ] ;
82+
83+ return (
84+ modelsArray
85+ . filter ( ( model : ContentModel ) => model ?. type === "block" )
86+ . map ( ( model ) => model as unknown as BlockModel ) || [ ]
87+ ) ;
88+ } , [ models ] ) ;
89+
90+ const variants = useMemo < ContentItem [ ] | [ ] > ( ( ) => {
91+ const contentItems = contents ? Object . values ( contents ) : [ ] ;
92+ if ( ! contentItems ?. length || ! blocks ?. length || isFetchingVariants ) {
93+ return [ ] ;
94+ }
95+
96+ const blockModelZUIDs = new Set ( blocks . map ( ( block ) => block ?. ZUID ) ) ;
97+ const validLangIDs = new Set ( languages . map ( ( lang ) => lang ?. ID ) ) ;
98+
99+ return contentItems . filter (
100+ ( content : ContentItem ) =>
101+ blockModelZUIDs . has ( content ?. meta ?. contentModelZUID ) &&
102+ validLangIDs . has ( content ?. meta ?. langID )
103+ ) ;
104+ } , [ contents , blocks , languages , isFetchingVariants ] ) ;
88105
89106 const parsedBlocks : BlockModel [ ] = useMemo ( ( ) => {
90107 if ( isLoading ) return [ ] ;
91108
92- const processedModels : BlockModel [ ] = ! blockModels ?. length
93- ? [ ]
94- : blockModels ?. map ( ( model : BlockModel ) => ( {
95- ZUID : model ?. ZUID ,
96- label : model ?. label ,
97- type : model ?. type ,
98- contentModelLabel : "" ,
99- contentModelZUID : "" ,
100- updatedAt : model ?. updatedAt ,
101- createdAt : model ?. createdAt ,
102- createdByUserZUID : model ?. createdByUserZUID ,
103- langID : null ,
104- url : `/blocks/${ model ?. ZUID } ` ,
105- } ) ) ;
106-
107- const processedContent = ! blockVariants ?. length
109+ const processedBlocks : BlockModel [ ] = ! blocks
108110 ? [ ]
109- : blockVariants ?. map ( ( item ) => {
110- const parentModel =
111- blockModelsMap ?. [ item ?. meta ?. contentModelZUID ] || null ;
111+ : blocks . map ( ( model : BlockModel ) => {
112112 return {
113- ZUID : item ?. meta ?. ZUID ,
114- label : item ?. web ?. metaTitle || item ?. web ?. metaLinkText ,
115- type : ! parentModel ? null : parentModel ?. type ,
116- contentModelZUID : item ?. meta ?. contentModelZUID ,
117- contentModelLabel : ! parentModel
118- ? null
119- : parentModel ?. label || parentModel ?. metaTitle ,
120- updatedAt : item ?. meta ?. updatedAt || item ?. web ?. updatedAt ,
121- createdAt : item ?. meta ?. createdAt || item ?. web ?. createdAt ,
122- createdByUserZUID :
123- item ?. meta ?. createdByUserZUID || item ?. web ?. createdByUserZUID ,
124- langID : item ?. meta ?. langID ,
125- url : `/blocks/${ item ?. meta ?. contentModelZUID } /${ item ?. meta ?. ZUID } ` ,
113+ ZUID : model ?. ZUID ,
114+ label : model ?. label ,
115+ title : model ?. label ,
116+ chipText : "Blocks" ,
117+ type : model ?. type ,
118+ contentModelLabel : "" ,
119+ contentModelZUID : "" ,
120+ updatedAt : model ?. updatedAt ,
121+ createdAt : model ?. createdAt ,
122+ createdByUserZUID : model ?. createdByUserZUID ,
123+ langID : defaultLanguage ?. ID ,
124+ url : `/blocks/${ model ?. ZUID } ` ,
126125 } ;
127126 } ) ;
128127
129- return [ ...processedModels , ...processedContent ]
130- . map ( ( item ) => ( {
128+ const processedVariants = variants . map ( ( item ) => {
129+ const blockModelsMap = blocks . length
130+ ? Object . fromEntries ( blocks . map ( ( model ) => [ model ?. ZUID , model ] ) )
131+ : { } ;
132+ const parentModel =
133+ blockModelsMap ?. [ item ?. meta ?. contentModelZUID ] || null ;
134+ const titlePrefix = ! item ?. meta ?. langID
135+ ? ""
136+ : `(${ languageMap ?. [ item ?. meta ?. langID ] ?. code } ) ` ;
137+ const chipText = parentModel ?. label || parentModel ?. metaTitle || null ;
138+ return {
139+ ZUID : item ?. meta ?. ZUID ,
140+ label : item ?. web ?. metaTitle || item ?. web ?. metaLinkText ,
141+ title : `${ titlePrefix } ${
142+ item ?. web ?. metaTitle || item ?. web ?. metaLinkText
143+ } `,
144+ chipText : ! chipText ? "Blocks" : `${ chipText } • Blocks` ,
145+ type : parentModel ?. type || null ,
146+ contentModelZUID : item ?. meta ?. contentModelZUID ,
147+ contentModelLabel : parentModel ?. label || parentModel ?. metaTitle || null ,
148+ updatedAt : item ?. meta ?. updatedAt || item ?. web ?. updatedAt ,
149+ createdAt : item ?. meta ?. createdAt || item ?. web ?. createdAt ,
150+ createdByUserZUID :
151+ item ?. meta ?. createdByUserZUID || item ?. web ?. createdByUserZUID ,
152+ langID : item ?. meta ?. langID ,
153+ url : `/blocks/${ item ?. meta ?. contentModelZUID } /${ item ?. meta ?. ZUID } ` ,
154+ } ;
155+ } ) ;
156+
157+ const allBlocks = [ ...processedBlocks , ...processedVariants ] . map ( ( item ) => {
158+ return {
131159 ...item ,
132- lang : languageMap [ item . langID ] ?. code ,
133160 createdByUserName : toProperCase ( usersMap [ item . createdByUserZUID ] || "" ) ,
134- title : item . label ,
135- } ) )
136- . filter ( ( item ) => {
137- if ( ! normalizedSearch ) return true ;
138-
139- const searchFields = [
140- item . ZUID ,
141- item . label ,
142- item . createdByUserName ,
143- item . title ,
144- item . contentModelZUID ,
145- item . type ,
146- item . contentModelLabel ,
147- ]
148- . join ( "\n" )
149- . toLowerCase ( ) ;
150-
151- return searchFields . includes ( normalizedSearch ) ;
152- } ) ;
161+ } ;
162+ } ) ;
163+
164+ // If search is empty or it's a block keyword, return all items
165+ if ( ! normalizedSearchTerm || showAll ) {
166+ return allBlocks ;
167+ }
168+
169+ // Filter based on search term
170+ return allBlocks ?. filter ( ( block ) => {
171+ const searchFields = [
172+ block ?. ZUID ,
173+ block ?. label ,
174+ block ?. createdByUserName ,
175+ block ?. title ,
176+ block ?. contentModelZUID ,
177+ block ?. type ,
178+ block ?. contentModelLabel ,
179+ ]
180+ . join ( "\n" )
181+ . toLowerCase ( ) ;
182+
183+ return searchFields . includes ( normalizedSearchTerm ) ;
184+ } ) ;
153185 } , [
154186 isLoading ,
155- blockVariants ,
156- blockModels ,
187+ variants ,
188+ blocks ,
189+ languages ,
190+ users ,
191+ normalizedSearchTerm ,
192+ showAll ,
157193 languageMap ,
158194 usersMap ,
159- blockModelsMap ,
160- normalizedSearch ,
161195 ] ) ;
162196
197+ const setBlockKeyword = useCallback ( ( term : string ) => {
198+ setSearchTerm ( term ) ;
199+ } , [ ] ) ;
200+
201+ useEffect ( ( ) => {
202+ // Fetch all block models and variants if user searches for "blockKeywords"
203+ if ( showAll && ! ! blocks ?. length ) {
204+ setIsFetchingVariants ( true ) ;
205+ Promise . all (
206+ blocks ?. map ( ( block ) => dispatch ( fetchItems ( block ?. ZUID ) ) )
207+ ) . then ( ( ) => {
208+ setIsFetchingVariants ( false ) ;
209+ } ) ;
210+ }
211+ } , [ showAll , blocks ] ) ;
212+
163213 return {
164214 blocks : parsedBlocks ,
165- setBlockKeyword : setSearchTerm ,
215+ setBlockKeyword,
166216 } ;
167217} ;
0 commit comments