mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #4824 from GGProGaming/Search
Resolve null searches with return text | Loading circle in search
This commit is contained in:
commit
167a13d974
4 changed files with 204 additions and 154 deletions
|
@ -70,6 +70,7 @@
|
||||||
- [tehciolo](https://github.com/tehciolo)
|
- [tehciolo](https://github.com/tehciolo)
|
||||||
- [scampower3](https://github.com/scampower3)
|
- [scampower3](https://github.com/scampower3)
|
||||||
- [LittleBigOwI] (https://github.com/LittleBigOwI/)
|
- [LittleBigOwI] (https://github.com/LittleBigOwI/)
|
||||||
|
- [Nate G](https://github.com/GGProGaming)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import React, { FunctionComponent, useCallback, useEffect, useState } from 'reac
|
||||||
import globalize from '../../scripts/globalize';
|
import globalize from '../../scripts/globalize';
|
||||||
import ServerConnections from '../ServerConnections';
|
import ServerConnections from '../ServerConnections';
|
||||||
import SearchResultsRow from './SearchResultsRow';
|
import SearchResultsRow from './SearchResultsRow';
|
||||||
|
import Loading from '../loading/LoadingComponent';
|
||||||
|
|
||||||
type SearchResultsProps = {
|
type SearchResultsProps = {
|
||||||
serverId?: string;
|
serverId?: string;
|
||||||
|
@ -45,6 +46,7 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({ serverId = windo
|
||||||
const [ books, setBooks ] = useState<BaseItemDto[]>([]);
|
const [ books, setBooks ] = useState<BaseItemDto[]>([]);
|
||||||
const [ people, setPeople ] = useState<BaseItemDto[]>([]);
|
const [ people, setPeople ] = useState<BaseItemDto[]>([]);
|
||||||
const [ collections, setCollections ] = useState<BaseItemDto[]>([]);
|
const [ collections, setCollections ] = useState<BaseItemDto[]>([]);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const getDefaultParameters = useCallback(() => ({
|
const getDefaultParameters = useCallback(() => ({
|
||||||
ParentId: parentId,
|
ParentId: parentId,
|
||||||
|
@ -114,99 +116,123 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({ serverId = windo
|
||||||
setCollections([]);
|
setCollections([]);
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
|
setIsLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
const apiClient = ServerConnections.getApiClient(serverId);
|
const apiClient = ServerConnections.getApiClient(serverId);
|
||||||
|
const fetchPromises = [];
|
||||||
|
|
||||||
// Movie libraries
|
// Movie libraries
|
||||||
if (!collectionType || isMovies(collectionType)) {
|
if (!collectionType || isMovies(collectionType)) {
|
||||||
|
fetchPromises.push(
|
||||||
// Movies row
|
// Movies row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Movie' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Movie' })
|
||||||
.then(result => setMovies(result.Items))
|
.then(result => setMovies(result.Items))
|
||||||
.catch(() => setMovies([]));
|
.catch(() => setMovies([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TV Show libraries
|
// TV Show libraries
|
||||||
if (!collectionType || isTVShows(collectionType)) {
|
if (!collectionType || isTVShows(collectionType)) {
|
||||||
|
fetchPromises.push(
|
||||||
// Shows row
|
// Shows row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Series' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Series' })
|
||||||
.then(result => setShows(result.Items))
|
.then(result => setShows(result.Items))
|
||||||
.catch(() => setShows([]));
|
.catch(() => setShows([])),
|
||||||
// Episodes row
|
// Episodes row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Episode' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Episode' })
|
||||||
.then(result => setEpisodes(result.Items))
|
.then(result => setEpisodes(result.Items))
|
||||||
.catch(() => setEpisodes([]));
|
.catch(() => setEpisodes([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// People are included for Movies and TV Shows
|
// People are included for Movies and TV Shows
|
||||||
if (!collectionType || isMovies(collectionType) || isTVShows(collectionType)) {
|
if (!collectionType || isMovies(collectionType) || isTVShows(collectionType)) {
|
||||||
|
fetchPromises.push(
|
||||||
// People row
|
// People row
|
||||||
fetchPeople(apiClient)
|
fetchPeople(apiClient)
|
||||||
.then(result => setPeople(result.Items))
|
.then(result => setPeople(result.Items))
|
||||||
.catch(() => setPeople([]));
|
.catch(() => setPeople([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Music libraries
|
// Music libraries
|
||||||
if (!collectionType || isMusic(collectionType)) {
|
if (!collectionType || isMusic(collectionType)) {
|
||||||
|
fetchPromises.push(
|
||||||
// Playlists row
|
// Playlists row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Playlist' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Playlist' })
|
||||||
.then(results => setPlaylists(results.Items))
|
.then(results => setPlaylists(results.Items))
|
||||||
.catch(() => setPlaylists([]));
|
.catch(() => setPlaylists([])),
|
||||||
// Artists row
|
// Artists row
|
||||||
fetchArtists(apiClient)
|
fetchArtists(apiClient)
|
||||||
.then(result => setArtists(result.Items))
|
.then(result => setArtists(result.Items))
|
||||||
.catch(() => setArtists([]));
|
.catch(() => setArtists([])),
|
||||||
// Albums row
|
// Albums row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' })
|
fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' })
|
||||||
.then(result => setAlbums(result.Items))
|
.then(result => setAlbums(result.Items))
|
||||||
.catch(() => setAlbums([]));
|
.catch(() => setAlbums([])),
|
||||||
// Songs row
|
// Songs row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Audio' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Audio' })
|
||||||
.then(result => setSongs(result.Items))
|
.then(result => setSongs(result.Items))
|
||||||
.catch(() => setSongs([]));
|
.catch(() => setSongs([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other libraries do not support in-library search currently
|
// Other libraries do not support in-library search currently
|
||||||
if (!collectionType) {
|
if (!collectionType) {
|
||||||
|
fetchPromises.push(
|
||||||
// Videos row
|
// Videos row
|
||||||
fetchItems(apiClient, {
|
fetchItems(apiClient, {
|
||||||
MediaTypes: 'Video',
|
MediaTypes: 'Video',
|
||||||
ExcludeItemTypes: 'Movie,Episode,TvChannel'
|
ExcludeItemTypes: 'Movie,Episode,TvChannel'
|
||||||
})
|
})
|
||||||
.then(result => setVideos(result.Items))
|
.then(result => setVideos(result.Items))
|
||||||
.catch(() => setVideos([]));
|
.catch(() => setVideos([])),
|
||||||
// Programs row
|
// Programs row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' })
|
fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' })
|
||||||
.then(result => setPrograms(result.Items))
|
.then(result => setPrograms(result.Items))
|
||||||
.catch(() => setPrograms([]));
|
.catch(() => setPrograms([])),
|
||||||
// Channels row
|
// Channels row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' })
|
fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' })
|
||||||
.then(result => setChannels(result.Items))
|
.then(result => setChannels(result.Items))
|
||||||
.catch(() => setChannels([]));
|
.catch(() => setChannels([])),
|
||||||
// Photo Albums row
|
// Photo Albums row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' })
|
fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' })
|
||||||
.then(result => setPhotoAlbums(result.Items))
|
.then(result => setPhotoAlbums(result.Items))
|
||||||
.catch(() => setPhotoAlbums([]));
|
.catch(() => setPhotoAlbums([])),
|
||||||
// Photos row
|
// Photos row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Photo' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Photo' })
|
||||||
.then(result => setPhotos(result.Items))
|
.then(result => setPhotos(result.Items))
|
||||||
.catch(() => setPhotos([]));
|
.catch(() => setPhotos([])),
|
||||||
// Audio Books row
|
// Audio Books row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' })
|
fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' })
|
||||||
.then(result => setAudioBooks(result.Items))
|
.then(result => setAudioBooks(result.Items))
|
||||||
.catch(() => setAudioBooks([]));
|
.catch(() => setAudioBooks([])),
|
||||||
// Books row
|
// Books row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Book' })
|
fetchItems(apiClient, { IncludeItemTypes: 'Book' })
|
||||||
.then(result => setBooks(result.Items))
|
.then(result => setBooks(result.Items))
|
||||||
.catch(() => setBooks([]));
|
.catch(() => setBooks([])),
|
||||||
// Collections row
|
// Collections row
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'BoxSet' })
|
fetchItems(apiClient, { IncludeItemTypes: 'BoxSet' })
|
||||||
.then(result => setCollections(result.Items))
|
.then(result => setCollections(result.Items))
|
||||||
.catch(() => setCollections([]));
|
.catch(() => setCollections([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
Promise.all(fetchPromises)
|
||||||
|
.then(() => {
|
||||||
|
setIsLoading(false); // Set loading to false when all fetch calls are done
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('An error occurred while fetching data:', error);
|
||||||
|
setIsLoading(false); // Set loading to false even if an error occurs
|
||||||
|
});
|
||||||
}, [collectionType, fetchArtists, fetchItems, fetchPeople, query, serverId]);
|
}, [collectionType, fetchArtists, fetchItems, fetchPeople, query, serverId]);
|
||||||
|
|
||||||
|
const allEmpty = [movies, shows, episodes, videos, programs, channels, playlists, artists, albums, songs, photoAlbums, photos, audioBooks, books, people, collections].every(arr => arr.length === 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
@ -216,6 +242,10 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({ serverId = windo
|
||||||
{ 'hide': !query || collectionType === 'livetv' }
|
{ 'hide': !query || collectionType === 'livetv' }
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loading />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('Movies')}
|
title={globalize.translate('Movies')}
|
||||||
items={movies}
|
items={movies}
|
||||||
|
@ -303,6 +333,13 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({ serverId = windo
|
||||||
items={people}
|
items={people}
|
||||||
cardOptions={{ coverImage: true }}
|
cardOptions={{ coverImage: true }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{allEmpty && query && !isLoading && (
|
||||||
|
<div className='sorry-text'>{globalize.translate('SearchResultsEmpty', query)}</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,3 +9,14 @@
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sorry-text {
|
||||||
|
font-size: 2em;
|
||||||
|
text-align: center;
|
||||||
|
font-family: inherit;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
|
@ -1428,6 +1428,7 @@
|
||||||
"SearchForMissingMetadata": "Search for missing metadata",
|
"SearchForMissingMetadata": "Search for missing metadata",
|
||||||
"SearchForSubtitles": "Search for Subtitles",
|
"SearchForSubtitles": "Search for Subtitles",
|
||||||
"SearchResults": "Search Results",
|
"SearchResults": "Search Results",
|
||||||
|
"SearchResultsEmpty": "Sorry! No results found for \"{0}\"",
|
||||||
"Season": "Season",
|
"Season": "Season",
|
||||||
"SecondarySubtitles": "Secondary Subtitles",
|
"SecondarySubtitles": "Secondary Subtitles",
|
||||||
"SelectAdminUsername": "Please select a username for the admin account.",
|
"SelectAdminUsername": "Please select a username for the admin account.",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue