Skip to content

Commit 7848ef3

Browse files
Add LoadingWrapper to indicate loading
This is the first iteration of the loading wrapper and is used to hide elements and indicate loading during the load time. It also has an optional loading text, which is rendered below the spinner. Resolves HSLdevcom/jore4#1499
1 parent bb816c4 commit 7848ef3

File tree

5 files changed

+80
-20
lines changed

5 files changed

+80
-20
lines changed

ui/src/components/routes-and-lines/search/SearchResultPage.tsx

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { usePagination } from '../../../hooks/usePagination';
55
import { Container, Row, Visible } from '../../../layoutComponents';
66
import { Path } from '../../../router/routeDetails';
77
import { CloseIconButton, Pagination } from '../../../uiComponents';
8+
import { LoadingWrapper } from '../../../uiComponents/LoadingWrapper';
89
import { RouteLineTableRowVariant } from '../../common/RouteLineTableRow';
910
import { ResultList } from '../../common/search/ResultList';
1011
import { ExportToolbar } from './ExportToolbar';
@@ -16,7 +17,7 @@ export const SearchResultPage = (): JSX.Element => {
1617
const { resultCount } = useSearchResults();
1718
const { t } = useTranslation();
1819
const { getPaginatedData } = usePagination();
19-
const { lines, reducedRoutes } = useSearchResults();
20+
const { lines, reducedRoutes, loading } = useSearchResults();
2021
const { basePath } = useBasePath();
2122
const itemsPerPage = 10;
2223

@@ -26,6 +27,7 @@ export const SearchResultPage = (): JSX.Element => {
2627
const testIds = {
2728
container: 'SearchResultsPage::Container',
2829
closeButton: 'SearchResultsPage::closeButton',
30+
loadingSearchResults: 'LoadingWrapper::loadingSearchResults',
2931
};
3032

3133
const determineDisplayInformation = () => {
@@ -60,23 +62,30 @@ export const SearchResultPage = (): JSX.Element => {
6062
/>
6163
</Row>
6264
<SearchContainer />
63-
<FiltersContainer />
64-
<ExportToolbar />
65-
<ResultList
66-
lines={displayedLines}
67-
routes={displayedRoutes}
68-
rowVariant={displayInformation.rowVariant}
69-
displayedType={queryParameters.filter.displayedType}
70-
/>
71-
<Visible visible={!!resultCount}>
72-
<div className="grid grid-cols-4">
73-
<Pagination
74-
className="col-span-2 col-start-2 pt-4"
75-
itemsPerPage={itemsPerPage}
76-
totalItemsCount={resultCount}
77-
/>
78-
</div>
79-
</Visible>
65+
<LoadingWrapper
66+
className="flex justify-center"
67+
loadingText={t('search.searching')}
68+
loading={loading}
69+
testId={testIds.loadingSearchResults}
70+
>
71+
<FiltersContainer />
72+
<ExportToolbar />
73+
<ResultList
74+
lines={displayedLines}
75+
routes={displayedRoutes}
76+
rowVariant={displayInformation.rowVariant}
77+
displayedType={queryParameters.filter.displayedType}
78+
/>
79+
<Visible visible={!!resultCount}>
80+
<div className="grid grid-cols-4">
81+
<Pagination
82+
className="col-span-2 col-start-2 pt-4"
83+
itemsPerPage={itemsPerPage}
84+
totalItemsCount={resultCount}
85+
/>
86+
</div>
87+
</Visible>
88+
</LoadingWrapper>
8089
</Container>
8190
);
8291
};

ui/src/hooks/search/useSearchResults.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const GQL_SEARCH_LINES_AND_ROUTES = gql`
2929
`;
3030

3131
export const useSearchResults = (): {
32+
loading: boolean;
3233
lines: LineTableRowFragment[];
3334
/** Routes reduced to only have 1 direction per label */
3435
reducedRoutes: RouteTableRowFragment[];
@@ -45,6 +46,7 @@ export const useSearchResults = (): {
4546
const result = useSearchLinesAndRoutesQuery(
4647
mapToVariables(searchQueryVariables),
4748
);
49+
const { loading } = result;
4850

4951
const lines = result.data?.route_line || [];
5052
const routes = result.data?.route_route || [];
@@ -84,6 +86,7 @@ export const useSearchResults = (): {
8486
const resultType = parsedSearchQueryParameters.filter.displayedType;
8587

8688
return {
89+
loading,
8790
lines,
8891
reducedRoutes,
8992
routes,

ui/src/locales/en-US/common.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@
294294
"resultCount": "{{ resultCount }} results",
295295
"searchPlaceholder": "Enter label",
296296
"searchLabel": "Search",
297-
"search": "Search"
297+
"search": "Search",
298+
"searching": "Searching..."
298299
},
299300
"tableHeaders": {
300301
"name": "Name",

ui/src/locales/fi-FI/common.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@
294294
"resultCount": "{{ resultCount }} hakutulosta",
295295
"searchPlaceholder": "Anna tunnus",
296296
"searchLabel": "Haku",
297-
"search": "Hae"
297+
"search": "Hae",
298+
"searching": "Haku käynnissä..."
298299
},
299300
"tableHeaders": {
300301
"name": "Nimi",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { FunctionComponent } from 'react';
2+
import { PulseLoader } from 'react-spinners';
3+
import { theme } from '../generated/theme';
4+
5+
interface Props {
6+
testId: string;
7+
loadingText?: string;
8+
className?: string;
9+
loading?: boolean;
10+
size?: number;
11+
color?: string;
12+
speedMultiplier?: number;
13+
}
14+
15+
/**
16+
* This loading wrapper will render a React spinner if the loading parameter is true,
17+
* but it will render the children if the loading parameter is false. So you can wrap the
18+
* elements that need to be hidden during the loading with this, hence the name.
19+
* There is also an optional loading text below the spinner.
20+
*/
21+
export const LoadingWrapper: FunctionComponent<Props> = ({
22+
testId,
23+
children,
24+
loadingText,
25+
className,
26+
loading = true,
27+
size = 25,
28+
color = theme.colors.brand,
29+
speedMultiplier = 0.7,
30+
}) => {
31+
if (loading) {
32+
return (
33+
<div data-testid={testId} className={className}>
34+
<div className="inline-flex flex-col items-center">
35+
<PulseLoader
36+
color={color}
37+
size={size}
38+
speedMultiplier={speedMultiplier}
39+
/>
40+
{loadingText && <span>{loadingText}</span>}
41+
</div>
42+
</div>
43+
);
44+
}
45+
return <>{children}</>;
46+
};

0 commit comments

Comments
 (0)