mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
First iteration
This commit is contained in:
parent
f173824c93
commit
2ffead179a
2 changed files with 197 additions and 154 deletions
8
jellyfin-web.code-workspace
Normal file
8
jellyfin-web.code-workspace
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
|
@ -45,6 +45,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,
|
||||||
|
@ -112,101 +113,124 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({ serverId = windo
|
||||||
setBooks([]);
|
setBooks([]);
|
||||||
setPeople([]);
|
setPeople([]);
|
||||||
setCollections([]);
|
setCollections([]);
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
|
setIsLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiClient = ServerConnections.getApiClient(serverId);
|
const apiClient = ServerConnections.getApiClient(serverId);
|
||||||
|
const fetchPromises = [];
|
||||||
|
|
||||||
// Movie libraries
|
// Movie libraries
|
||||||
if (!collectionType || isMovies(collectionType)) {
|
if (!collectionType || isMovies(collectionType)) {
|
||||||
// Movies row
|
fetchPromises.push(
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Movie' })
|
// Movies row
|
||||||
.then(result => setMovies(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Movie' })
|
||||||
.catch(() => setMovies([]));
|
.then(result => setMovies(result.Items))
|
||||||
|
.catch(() => setMovies([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TV Show libraries
|
// TV Show libraries
|
||||||
if (!collectionType || isTVShows(collectionType)) {
|
if (!collectionType || isTVShows(collectionType)) {
|
||||||
// Shows row
|
fetchPromises.push(
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Series' })
|
// Shows row
|
||||||
.then(result => setShows(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Series' })
|
||||||
.catch(() => setShows([]));
|
.then(result => setShows(result.Items))
|
||||||
// Episodes row
|
.catch(() => setShows([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Episode' })
|
// Episodes row
|
||||||
.then(result => setEpisodes(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Episode' })
|
||||||
.catch(() => setEpisodes([]));
|
.then(result => setEpisodes(result.Items))
|
||||||
|
.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)) {
|
||||||
// People row
|
fetchPromises.push(
|
||||||
fetchPeople(apiClient)
|
// People row
|
||||||
.then(result => setPeople(result.Items))
|
fetchPeople(apiClient)
|
||||||
.catch(() => setPeople([]));
|
.then(result => setPeople(result.Items))
|
||||||
|
.catch(() => setPeople([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Music libraries
|
// Music libraries
|
||||||
if (!collectionType || isMusic(collectionType)) {
|
if (!collectionType || isMusic(collectionType)) {
|
||||||
// Playlists row
|
fetchPromises.push(
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Playlist' })
|
// Playlists row
|
||||||
.then(results => setPlaylists(results.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Playlist' })
|
||||||
.catch(() => setPlaylists([]));
|
.then(results => setPlaylists(results.Items))
|
||||||
// Artists row
|
.catch(() => setPlaylists([])),
|
||||||
fetchArtists(apiClient)
|
// Artists row
|
||||||
.then(result => setArtists(result.Items))
|
fetchArtists(apiClient)
|
||||||
.catch(() => setArtists([]));
|
.then(result => setArtists(result.Items))
|
||||||
// Albums row
|
.catch(() => setArtists([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' })
|
// Albums row
|
||||||
.then(result => setAlbums(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' })
|
||||||
.catch(() => setAlbums([]));
|
.then(result => setAlbums(result.Items))
|
||||||
// Songs row
|
.catch(() => setAlbums([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Audio' })
|
// Songs row
|
||||||
.then(result => setSongs(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Audio' })
|
||||||
.catch(() => setSongs([]));
|
.then(result => setSongs(result.Items))
|
||||||
|
.catch(() => setSongs([]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other libraries do not support in-library search currently
|
// Other libraries do not support in-library search currently
|
||||||
if (!collectionType) {
|
if (!collectionType) {
|
||||||
// Videos row
|
fetchPromises.push(
|
||||||
fetchItems(apiClient, {
|
// Videos row
|
||||||
MediaTypes: 'Video',
|
fetchItems(apiClient, {
|
||||||
ExcludeItemTypes: 'Movie,Episode,TvChannel'
|
MediaTypes: 'Video',
|
||||||
})
|
ExcludeItemTypes: 'Movie,Episode,TvChannel'
|
||||||
.then(result => setVideos(result.Items))
|
})
|
||||||
.catch(() => setVideos([]));
|
.then(result => setVideos(result.Items))
|
||||||
// Programs row
|
.catch(() => setVideos([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' })
|
// Programs row
|
||||||
.then(result => setPrograms(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' })
|
||||||
.catch(() => setPrograms([]));
|
.then(result => setPrograms(result.Items))
|
||||||
// Channels row
|
.catch(() => setPrograms([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' })
|
// Channels row
|
||||||
.then(result => setChannels(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' })
|
||||||
.catch(() => setChannels([]));
|
.then(result => setChannels(result.Items))
|
||||||
// Photo Albums row
|
.catch(() => setChannels([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' })
|
// Photo Albums row
|
||||||
.then(result => setPhotoAlbums(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' })
|
||||||
.catch(() => setPhotoAlbums([]));
|
.then(result => setPhotoAlbums(result.Items))
|
||||||
// Photos row
|
.catch(() => setPhotoAlbums([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Photo' })
|
// Photos row
|
||||||
.then(result => setPhotos(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Photo' })
|
||||||
.catch(() => setPhotos([]));
|
.then(result => setPhotos(result.Items))
|
||||||
// Audio Books row
|
.catch(() => setPhotos([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' })
|
// Audio Books row
|
||||||
.then(result => setAudioBooks(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' })
|
||||||
.catch(() => setAudioBooks([]));
|
.then(result => setAudioBooks(result.Items))
|
||||||
// Books row
|
.catch(() => setAudioBooks([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'Book' })
|
// Books row
|
||||||
.then(result => setBooks(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'Book' })
|
||||||
.catch(() => setBooks([]));
|
.then(result => setBooks(result.Items))
|
||||||
// Collections row
|
.catch(() => setBooks([])),
|
||||||
fetchItems(apiClient, { IncludeItemTypes: 'BoxSet' })
|
// Collections row
|
||||||
.then(result => setCollections(result.Items))
|
fetchItems(apiClient, { IncludeItemTypes: 'BoxSet' })
|
||||||
.catch(() => setCollections([]));
|
.then(result => setCollections(result.Items))
|
||||||
|
.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,93 +240,104 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({ serverId = windo
|
||||||
{ 'hide': !query || collectionType === 'livetv' }
|
{ 'hide': !query || collectionType === 'livetv' }
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<SearchResultsRow
|
{isLoading ? (
|
||||||
title={globalize.translate('Movies')}
|
<div>Loading...</div> // Replace this with your preferred progress indicator
|
||||||
items={movies}
|
) : (
|
||||||
cardOptions={{ showYear: true }}
|
<>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('Movies')}
|
||||||
title={globalize.translate('Shows')}
|
items={movies}
|
||||||
items={shows}
|
cardOptions={{ showYear: true }}
|
||||||
cardOptions={{ showYear: true }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('Shows')}
|
||||||
title={globalize.translate('Episodes')}
|
items={shows}
|
||||||
items={episodes}
|
cardOptions={{ showYear: true }}
|
||||||
cardOptions={{
|
/>
|
||||||
coverImage: true,
|
<SearchResultsRow
|
||||||
showParentTitle: true
|
title={globalize.translate('Episodes')}
|
||||||
}}
|
items={episodes}
|
||||||
/>
|
cardOptions={{
|
||||||
<SearchResultsRow
|
coverImage: true,
|
||||||
title={globalize.translate('HeaderVideos')}
|
showParentTitle: true
|
||||||
items={videos}
|
}}
|
||||||
cardOptions={{ showParentTitle: true }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('HeaderVideos')}
|
||||||
title={globalize.translate('Programs')}
|
items={videos}
|
||||||
items={programs}
|
cardOptions={{ showParentTitle: true }}
|
||||||
cardOptions={{
|
/>
|
||||||
preferThumb: true,
|
<SearchResultsRow
|
||||||
inheritThumb: false,
|
title={globalize.translate('Programs')}
|
||||||
showParentTitleOrTitle: true,
|
items={programs}
|
||||||
showTitle: false,
|
cardOptions={{
|
||||||
coverImage: true,
|
preferThumb: true,
|
||||||
overlayMoreButton: true,
|
inheritThumb: false,
|
||||||
showAirTime: true,
|
showParentTitleOrTitle: true,
|
||||||
showAirDateTime: true,
|
showTitle: false,
|
||||||
showChannelName: true
|
coverImage: true,
|
||||||
}}
|
overlayMoreButton: true,
|
||||||
/>
|
showAirTime: true,
|
||||||
<SearchResultsRow
|
showAirDateTime: true,
|
||||||
title={globalize.translate('Channels')}
|
showChannelName: true
|
||||||
items={channels}
|
}}
|
||||||
cardOptions={{ shape: 'square' }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('Channels')}
|
||||||
title={globalize.translate('Playlists')}
|
items={channels}
|
||||||
items={playlists}
|
cardOptions={{ shape: 'square' }}
|
||||||
/>
|
/>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('Artists')}
|
title={globalize.translate('Playlists')}
|
||||||
items={artists}
|
items={playlists}
|
||||||
cardOptions={{ coverImage: true }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('Artists')}
|
||||||
title={globalize.translate('Albums')}
|
items={artists}
|
||||||
items={albums}
|
cardOptions={{ coverImage: true }}
|
||||||
cardOptions={{ showParentTitle: true }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('Albums')}
|
||||||
title={globalize.translate('Songs')}
|
items={albums}
|
||||||
items={songs}
|
cardOptions={{ showParentTitle: true }}
|
||||||
cardOptions={{ showParentTitle: true }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
<SearchResultsRow
|
title={globalize.translate('Songs')}
|
||||||
title={globalize.translate('HeaderPhotoAlbums')}
|
items={songs}
|
||||||
items={photoAlbums}
|
cardOptions={{ showParentTitle: true }}
|
||||||
/>
|
/>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('Photos')}
|
title={globalize.translate('HeaderPhotoAlbums')}
|
||||||
items={photos}
|
items={photoAlbums}
|
||||||
/>
|
/>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('HeaderAudioBooks')}
|
title={globalize.translate('Photos')}
|
||||||
items={audioBooks}
|
items={photos}
|
||||||
/>
|
/>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('Books')}
|
title={globalize.translate('HeaderAudioBooks')}
|
||||||
items={books}
|
items={audioBooks}
|
||||||
/>
|
/>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('Collections')}
|
title={globalize.translate('Books')}
|
||||||
items={collections}
|
items={books}
|
||||||
/>
|
/>
|
||||||
<SearchResultsRow
|
<SearchResultsRow
|
||||||
title={globalize.translate('People')}
|
title={globalize.translate('Collections')}
|
||||||
items={people}
|
items={collections}
|
||||||
cardOptions={{ coverImage: true }}
|
/>
|
||||||
/>
|
<SearchResultsRow
|
||||||
|
title={globalize.translate('People')}
|
||||||
|
items={people}
|
||||||
|
cardOptions={{ coverImage: true }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{allEmpty && !isLoading && (
|
||||||
|
<div>Sorry, nothing's here :/</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue