Skip to content

Commit d288663

Browse files
authored
Fix undefined value (#418)
Signed-off-by: Ghazwa REHILI <[email protected]>
1 parent 6678c5a commit d288663

File tree

4 files changed

+103
-35
lines changed

4 files changed

+103
-35
lines changed

src/components/app-top-bar.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import GridExploreLogoLight from '../images/GridExplore_logo_light.svg?react';
2222
import GridExploreLogoDark from '../images/GridExplore_logo_dark.svg?react';
2323
import { setAppsAndUrls } from '../redux/actions';
2424
import AppPackage from '../../package.json';
25-
import SearchBar from './search/search-bar';
25+
import { SearchBar } from './search/search-bar';
2626

2727
const AppTopBar = ({ user, userManager }) => {
2828
const navigate = useNavigate();

src/components/search/search-bar.jsx renamed to src/components/search/search-bar.tsx

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
7-
import React, { useCallback, useEffect, useRef, useState } from 'react';
7+
import {
8+
Fragment,
9+
FunctionComponent,
10+
Ref,
11+
SyntheticEvent,
12+
useCallback,
13+
useEffect,
14+
useRef,
15+
useState,
16+
} from 'react';
817
import { Autocomplete, TextField } from '@mui/material';
918
import {
1019
fetchDirectoryContent,
@@ -16,23 +25,38 @@ import { useDispatch, useSelector } from 'react-redux';
1625
import { setSelectedDirectory, setTreeData } from '../../redux/actions';
1726
import { updatedTree } from '../tree-views-container';
1827
import { useIntl } from 'react-intl';
19-
import SearchItem from './search-item';
28+
import { SearchItem } from './search-item';
29+
import { IDirectory, ITreeData, ReduxState } from '../../redux/reducer.type';
2030

2131
export const SEARCH_FETCH_TIMEOUT_MILLIS = 1000; // 1 second
2232

23-
export const SearchBar = ({ inputRef }) => {
33+
interface matchingElementProps {
34+
id: string;
35+
name: string;
36+
type: string;
37+
pathName: string[];
38+
pathUuid: string[];
39+
}
40+
41+
interface SearchBarProps {
42+
inputRef: Ref<any>;
43+
}
44+
45+
export const SearchBar: FunctionComponent<SearchBarProps> = ({ inputRef }) => {
2446
const dispatch = useDispatch();
2547
const { snackError } = useSnackMessage();
26-
const [elementsFound, setElementsFound] = useState([]);
48+
const [elementsFound, setElementsFound] = useState<matchingElementProps[]>(
49+
[]
50+
);
2751
const [inputValue, onInputChange] = useState('');
2852
const lastSearchTermRef = useRef('');
2953
const [loading, setLoading] = useState(false);
30-
const treeData = useSelector((state) => state.treeData);
31-
const treeDataRef = useRef();
54+
const treeData = useSelector((state: ReduxState) => state.treeData);
55+
const treeDataRef = useRef<ITreeData>();
3256
const intl = useIntl();
3357
treeDataRef.current = treeData;
3458
const searchMatchingEquipments = useCallback(
35-
(searchTerm) => {
59+
(searchTerm: string) => {
3660
lastSearchTermRef.current = searchTerm;
3761
searchTerm &&
3862
searchElementsInfos(searchTerm)
@@ -59,7 +83,7 @@ export const SearchBar = ({ inputRef }) => {
5983
);
6084

6185
const handleChangeInput = useCallback(
62-
(searchTerm) => {
86+
(searchTerm: string) => {
6387
onInputChange(searchTerm);
6488
searchTerm && setLoading(true);
6589
debouncedSearchMatchingElements(searchTerm);
@@ -72,9 +96,9 @@ export const SearchBar = ({ inputRef }) => {
7296
}, [elementsFound]);
7397

7498
const renderOptionItem = useCallback(
75-
(props, option) => {
99+
(props: any, option: matchingElementProps) => {
76100
const matchingElement = elementsFound.find(
77-
(element) => element.id === option.id
101+
(element: matchingElementProps) => element.id === option.id
78102
);
79103
return (
80104
<SearchItem
@@ -88,7 +112,10 @@ export const SearchBar = ({ inputRef }) => {
88112
);
89113

90114
const updateMapData = useCallback(
91-
(nodeId, children) => {
115+
(nodeId: string, children: IDirectory) => {
116+
if (!treeDataRef.current) {
117+
return;
118+
}
92119
let [newRootDirectories, newMapData] = updatedTree(
93120
treeDataRef.current.rootDirectories,
94121
treeDataRef.current.mapData,
@@ -106,24 +133,25 @@ export const SearchBar = ({ inputRef }) => {
106133
);
107134

108135
const handleDispatchDirectory = useCallback(
109-
(elementUuidPath) => {
110-
const selectedDirectory =
111-
treeDataRef.current.mapData[elementUuidPath];
136+
(elementUuidPath: string | undefined) => {
137+
if (treeDataRef.current && elementUuidPath !== undefined) {
138+
const selectedDirectory =
139+
treeDataRef.current.mapData[elementUuidPath];
112140

113-
dispatch(setSelectedDirectory(selectedDirectory));
141+
dispatch(setSelectedDirectory(selectedDirectory));
142+
}
114143
},
115144
[dispatch]
116145
);
117146

118147
const handleMatchingElement = useCallback(
119-
(event, data) => {
148+
(event: SyntheticEvent, data: matchingElementProps | string | null) => {
120149
const matchingElement = elementsFound.find(
121-
(element) => element === data
150+
(element: matchingElementProps) => element === data
122151
);
123152
if (matchingElement !== undefined) {
124153
const elementUuidPath = matchingElement?.pathUuid.reverse();
125-
126-
const promises = elementUuidPath.map((e) => {
154+
const promises = elementUuidPath.map((e: string) => {
127155
return fetchDirectoryContent(e)
128156
.then((res) => {
129157
updateMapData(e, res);
@@ -159,9 +187,21 @@ export const SearchBar = ({ inputRef }) => {
159187
inputValue={inputValue}
160188
onInputChange={(_, data) => handleChangeInput(data)}
161189
onChange={handleMatchingElement}
162-
key={(option) => option.id}
190+
getOptionKey={(option) => {
191+
if (typeof option === 'string') {
192+
return option;
193+
} else {
194+
return option.id;
195+
}
196+
}}
163197
options={loading ? [] : elementsFound}
164-
getOptionLabel={(option) => option.name}
198+
getOptionLabel={(option) => {
199+
if (typeof option === 'string') {
200+
return inputValue;
201+
} else {
202+
return option.name;
203+
}
204+
}}
165205
loading={loading}
166206
renderOption={renderOptionItem}
167207
renderInput={(params) => (
@@ -176,10 +216,10 @@ export const SearchBar = ({ inputRef }) => {
176216
InputProps={{
177217
...params.InputProps,
178218
startAdornment: (
179-
<React.Fragment>
219+
<Fragment>
180220
<Search />
181221
{params.InputProps.startAdornment}
182-
</React.Fragment>
222+
</Fragment>
183223
),
184224
}}
185225
/>
@@ -188,5 +228,3 @@ export const SearchBar = ({ inputRef }) => {
188228
</>
189229
);
190230
};
191-
192-
export default SearchBar;

src/components/search/search-item.jsx renamed to src/components/search/search-item.tsx

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import { getFileIcon } from '@gridsuite/commons-ui';
88
import Grid from '@mui/material/Grid';
99
import Typography from '@mui/material/Typography';
1010
import { FormattedMessage } from 'react-intl';
11+
import { FunctionComponent } from 'react';
12+
import { Theme } from '@mui/material';
1113

1214
const styles = {
13-
icon: (theme) => ({
15+
icon: (theme: Theme) => ({
1416
marginRight: theme.spacing(2),
1517
width: '18px',
1618
height: '18px',
@@ -20,7 +22,7 @@ const styles = {
2022
textOverflow: 'ellipsis',
2123
display: 'inline-block',
2224
},
23-
grid2: (theme) => ({
25+
grid2: (theme: Theme) => ({
2426
marginRight: theme.spacing(2),
2527
overflow: 'hidden',
2628
textOverflow: 'ellipsis',
@@ -29,9 +31,29 @@ const styles = {
2931
}),
3032
};
3133

32-
function HighlightedText({ text, highlight }) {
33-
const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
34+
interface HighlightedTextProps {
35+
text: string;
36+
highlight: string;
37+
}
38+
39+
interface SearchItemProps {
40+
matchingElement: matchingElementProps;
41+
inputValue: string;
42+
}
43+
44+
interface matchingElementProps {
45+
id: string;
46+
name: string;
47+
type: string;
48+
pathName: string[];
49+
pathUuid: string[];
50+
}
3451

52+
export const HighlightedText: FunctionComponent<HighlightedTextProps> = ({
53+
text,
54+
highlight,
55+
}) => {
56+
const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
3557
return (
3658
<span>
3759
{parts.map((part, i) =>
@@ -45,9 +67,13 @@ function HighlightedText({ text, highlight }) {
4567
)}
4668
</span>
4769
);
48-
}
70+
};
4971

50-
function SearchItem({ matchingElement, inputValue, ...othersProps }) {
72+
export const SearchItem: FunctionComponent<SearchItemProps> = ({
73+
matchingElement,
74+
inputValue,
75+
...othersProps
76+
}) => {
5177
return (
5278
<li {...othersProps}>
5379
<>
@@ -69,6 +95,4 @@ function SearchItem({ matchingElement, inputValue, ...othersProps }) {
6995
</>
7096
</li>
7197
);
72-
}
73-
74-
export default SearchItem;
98+
};

src/redux/reducer.type.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,14 @@ export interface IDirectory {
3838
parentUuid: null | UUID;
3939
}
4040

41+
export interface ITreeData {
42+
rootDirectories: IDirectory[];
43+
mapData: Record<string, any>;
44+
}
45+
4146
export interface ReduxState {
4247
activeDirectory: UUID;
4348
selectedDirectory: IDirectory;
49+
treeData: ITreeData;
4450
user: IUser;
4551
}

0 commit comments

Comments
 (0)