1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Refactoring duplicates code

This commit is contained in:
grafixeyehero 2022-08-21 03:09:22 +03:00
parent 368a6064c2
commit cf137497a0
20 changed files with 491 additions and 513 deletions

View file

@ -145,9 +145,15 @@
windowSize = null; windowSize = null;
} }
/**
* @typedef {Object} windowSize
* @property {number} innerHeight - window innerHeight.
* @property {number} innerWidth - window innerWidth.
*/
/** /**
* Returns window size. * Returns window size.
* @returns {Object} Window size. * @returns {windowSize} Window size.
*/ */
export function getWindowSize() { export function getWindowSize() {
if (!windowSize) { if (!windowSize) {

View file

@ -467,11 +467,17 @@ export class UserSettings {
return this.get('soundeffects', false); return this.get('soundeffects', false);
} }
/**
* @typedef {Object} Query
* @property {number} StartIndex - query StartIndex.
* @property {number} Limit - query Limit.
*/
/** /**
* Load query settings. * Load query settings.
* @param {string} key - Query key. * @param {string} key - Query key.
* @param {Object} query - Query base. * @param {Object} query - Query base.
* @return {Object} Query. * @return {Query} Query.
*/ */
loadQuerySettings(key, query) { loadQuerySettings(key, query) {
let values = this.get(key); let values = this.get(key);

View file

@ -1065,6 +1065,7 @@
"MessageItemsAdded": "Items added.", "MessageItemsAdded": "Items added.",
"MessageItemSaved": "Item saved.", "MessageItemSaved": "Item saved.",
"MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.", "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.",
"MessageNoItemsAvailable": "No Items are currently available.",
"MessageNoFavoritesAvailable": "No favorites are currently available.", "MessageNoFavoritesAvailable": "No favorites are currently available.",
"MessageNoAvailablePlugins": "No available plugins.", "MessageNoAvailablePlugins": "No available plugins.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the '+' button to start creating collections.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the '+' button to start creating collections.",

View file

@ -1,4 +1,4 @@
import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; import React, { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react';
import AlphaPicker from '../../components/alphaPicker/alphaPicker'; import AlphaPicker from '../../components/alphaPicker/alphaPicker';
import { IQuery } from './type'; import { IQuery } from './type';
@ -13,11 +13,7 @@ const AlphaPickerContainer: FunctionComponent<AlphaPickerProps> = ({ query, relo
alphaPicker?.updateControls(query); alphaPicker?.updateControls(query);
useEffect(() => { const onAlphaPickerChange = useCallback((e) => {
const alphaPickerElement = element.current?.querySelector('.alphaPicker');
if (alphaPickerElement) {
alphaPickerElement.addEventListener('alphavaluechanged', (e) => {
const newValue = (e as CustomEvent).detail.value; const newValue = (e as CustomEvent).detail.value;
if (newValue === '#') { if (newValue === '#') {
query.NameLessThan = 'A'; query.NameLessThan = 'A';
@ -28,19 +24,24 @@ const AlphaPickerContainer: FunctionComponent<AlphaPickerProps> = ({ query, relo
} }
query.StartIndex = 0; query.StartIndex = 0;
reloadItems(); reloadItems();
}); }, [query, reloadItems]);
useEffect(() => {
const alphaPickerElement = element.current?.querySelector('.alphaPicker');
setAlphaPicker(new AlphaPicker({ setAlphaPicker(new AlphaPicker({
element: alphaPickerElement, element: alphaPickerElement,
valueChangeEvent: 'click' valueChangeEvent: 'click'
})); }));
alphaPickerElement.classList.add('alphaPicker-fixed-right'); if (alphaPickerElement) {
alphaPickerElement.addEventListener('alphavaluechanged', onAlphaPickerChange);
} }
}, [query, reloadItems, setAlphaPicker]); }, [onAlphaPickerChange]);
return ( return (
<div ref={element}> <div ref={element}>
<div className='alphaPicker alphaPicker-fixed alphaPicker-vertical alphabetPicker-right' /> <div className='alphaPicker alphaPicker-fixed alphaPicker-fixed-right alphaPicker-vertical alphabetPicker-right' />
</div> </div>
); );
}; };

View file

@ -5,17 +5,18 @@ import { IQuery } from './type';
type FilterProps = { type FilterProps = {
query: IQuery; query: IQuery;
getFilterMode: () => string | null;
reloadItems: () => void; reloadItems: () => void;
} }
const Filter: FunctionComponent<FilterProps> = ({ query, reloadItems }: FilterProps) => { const Filter: FunctionComponent<FilterProps> = ({ query, getFilterMode, reloadItems }: FilterProps) => {
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
const showFilterMenu = useCallback(() => { const showFilterMenu = useCallback(() => {
import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => {
const filterDialog = new filterDialogFactory({ const filterDialog = new filterDialogFactory({
query: query, query: query,
mode: 'movies', mode: getFilterMode(),
serverId: window.ApiClient.serverId() serverId: window.ApiClient.serverId()
}); });
Events.on(filterDialog, 'filterchange', () => { Events.on(filterDialog, 'filterchange', () => {
@ -24,15 +25,13 @@ const Filter: FunctionComponent<FilterProps> = ({ query, reloadItems }: FilterPr
}); });
filterDialog.show(); filterDialog.show();
}); });
}, [query, reloadItems]); }, [getFilterMode, query, reloadItems]);
useEffect(() => { useEffect(() => {
const btnFilter = element.current?.querySelector('.btnFilter'); const btnFilter = element.current?.querySelector('.btnFilter');
if (btnFilter) { if (btnFilter) {
btnFilter.addEventListener('click', () => { btnFilter.addEventListener('click', showFilterMenu);
showFilterMenu();
});
} }
}, [showFilterMenu]); }, [showFilterMenu]);

View file

@ -126,13 +126,8 @@ const GenresItemsContainer: FunctionComponent<GenresItemsContainerProps> = ({ to
html += '</a>'; html += '</a>';
html += '</div>'; html += '</div>';
if (enableScrollX()) { if (enableScrollX()) {
let scrollXClass = 'scrollX hiddenScrollX'; html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x lazy" data-id="' + item.Id + '">';
if (layoutManager.tv) {
scrollXClass += 'smoothScrollX padded-top-focusscale padded-bottom-focusscale';
}
html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' lazy padded-left padded-right" data-id="' + item.Id + '">';
} else { } else {
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap lazy padded-left padded-right" data-id="' + item.Id + '">'; html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap lazy padded-left padded-right" data-id="' + item.Id + '">';
} }

View file

@ -12,11 +12,12 @@ import { IQuery } from './type';
type ItemsContainerProps = { type ItemsContainerProps = {
getCurrentViewStyle: () => string; getCurrentViewStyle: () => string;
query: IQuery; query: IQuery;
getContext: () => string | null;
items?: BaseItemDto[] | null; items?: BaseItemDto[] | null;
noItemsMessage?: string; noItemsMessage?: string;
} }
const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentViewStyle, query, items = [], noItemsMessage }: ItemsContainerProps) => { const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentViewStyle, query, getContext, items = [], noItemsMessage }: ItemsContainerProps) => {
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
const viewStyle = getCurrentViewStyle(); const viewStyle = getCurrentViewStyle();
@ -28,7 +29,7 @@ const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentView
items: items, items: items,
shape: 'backdrop', shape: 'backdrop',
preferThumb: true, preferThumb: true,
context: 'movies', context: getContext(),
lazy: true, lazy: true,
overlayPlayButton: true, overlayPlayButton: true,
showTitle: true, showTitle: true,
@ -40,7 +41,7 @@ const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentView
items: items, items: items,
shape: 'backdrop', shape: 'backdrop',
preferThumb: true, preferThumb: true,
context: 'movies', context: getContext(),
lazy: true, lazy: true,
cardLayout: true, cardLayout: true,
showTitle: true, showTitle: true,
@ -52,20 +53,20 @@ const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentView
items: items, items: items,
shape: 'banner', shape: 'banner',
preferBanner: true, preferBanner: true,
context: 'movies', context: getContext(),
lazy: true lazy: true
}); });
} else if (viewStyle == 'List') { } else if (viewStyle == 'List') {
html = listview.getListViewHtml({ html = listview.getListViewHtml({
items: items, items: items,
context: 'movies', context: getContext(),
sortBy: query.SortBy sortBy: query.SortBy
}); });
} else if (viewStyle == 'PosterCard') { } else if (viewStyle == 'PosterCard') {
html = cardBuilder.getCardsHtml(items, { html = cardBuilder.getCardsHtml(items, {
items: items, items: items,
shape: 'portrait', shape: 'portrait',
context: 'movies', context: getContext(),
showTitle: true, showTitle: true,
showYear: true, showYear: true,
centerText: true, centerText: true,
@ -76,7 +77,7 @@ const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentView
html = cardBuilder.getCardsHtml(items, { html = cardBuilder.getCardsHtml(items, {
items: items, items: items,
shape: 'portrait', shape: 'portrait',
context: 'movies', context: getContext(),
overlayPlayButton: true, overlayPlayButton: true,
showTitle: true, showTitle: true,
showYear: true, showYear: true,
@ -96,14 +97,14 @@ const ItemsContainer: FunctionComponent<ItemsContainerProps> = ({ getCurrentView
const itemsContainer = element.current?.querySelector('.itemsContainer') as HTMLDivElement; const itemsContainer = element.current?.querySelector('.itemsContainer') as HTMLDivElement;
itemsContainer.innerHTML = html; itemsContainer.innerHTML = html;
imageLoader.lazyChildren(itemsContainer); imageLoader.lazyChildren(itemsContainer);
}, [query.SortBy, items, noItemsMessage, viewStyle]); }, [query.SortBy, items, noItemsMessage, viewStyle, getContext]);
const cssClass = viewStyle == 'List' ? 'vertical-list' : 'vertical-wrap'; const cssClass = viewStyle == 'List' ? 'vertical-list' : 'vertical-wrap';
return ( return (
<div ref={element}> <div ref={element}>
<ItemsContainerElement <ItemsContainerElement
className={`itemsContainer ${cssClass} centered padded-left padded-right`} className={`itemsContainer ${cssClass} centered padded-left padded-right padded-right-withalphapicker`}
/> />
</div> </div>
); );

View file

@ -1,14 +1,11 @@
import React, { FunctionComponent, useEffect, useRef } from 'react'; import React, { FunctionComponent, useCallback, useEffect, useRef } from 'react';
import IconButtonElement from '../../elements/IconButtonElement'; import IconButtonElement from '../../elements/IconButtonElement';
const NewCollection: FunctionComponent = () => { const NewCollection: FunctionComponent = () => {
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
useEffect(() => { const showCollectionEditor = useCallback(() => {
const btnNewCollection = element.current?.querySelector('.btnNewCollection') as HTMLButtonElement;
if (btnNewCollection) {
btnNewCollection.addEventListener('click', () => {
import('../../components/collectionEditor/collectionEditor').then(({default: CollectionEditor}) => { import('../../components/collectionEditor/collectionEditor').then(({default: CollectionEditor}) => {
const serverId = window.ApiClient.serverId(); const serverId = window.ApiClient.serverId();
const collectionEditor = new CollectionEditor(); const collectionEditor = new CollectionEditor();
@ -17,10 +14,15 @@ const NewCollection: FunctionComponent = () => {
serverId: serverId serverId: serverId
}); });
}); });
});
}
}, []); }, []);
useEffect(() => {
const btnNewCollection = element.current?.querySelector('.btnNewCollection');
if (btnNewCollection) {
btnNewCollection.addEventListener('click', showCollectionEditor);
}
}, [showCollectionEditor]);
return ( return (
<div ref={element}> <div ref={element}>
<IconButtonElement <IconButtonElement

View file

@ -1,8 +1,7 @@
import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client'; import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
import React, { FunctionComponent, useEffect, useRef } from 'react'; import React, { FunctionComponent, useCallback, useEffect, useRef } from 'react';
import libraryBrowser from '../../scripts/libraryBrowser'; import IconButtonElement from '../../elements/IconButtonElement';
import globalize from '../../scripts/globalize';
import * as userSettings from '../../scripts/settings/userSettings';
import { IQuery } from './type'; import { IQuery } from './type';
type PaginationProps = { type PaginationProps = {
@ -12,49 +11,72 @@ type PaginationProps = {
} }
const Pagination: FunctionComponent<PaginationProps> = ({ query, itemsResult = {}, reloadItems }: PaginationProps) => { const Pagination: FunctionComponent<PaginationProps> = ({ query, itemsResult = {}, reloadItems }: PaginationProps) => {
const startIndex = query.StartIndex;
const limit = query.Limit;
const totalRecordCount = itemsResult.TotalRecordCount || 0;
const recordsEnd = Math.min(startIndex + limit, totalRecordCount);
const showControls = limit < totalRecordCount;
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
useEffect(() => {
function onNextPageClick() { const onNextPageClick = useCallback(() => {
if (userSettings.libraryPageSize(undefined) > 0) { if (query.Limit > 0) {
query.StartIndex += query.Limit; query.StartIndex += query.Limit;
} }
reloadItems(); reloadItems();
} }, [query, reloadItems]);
function onPreviousPageClick() { const onPreviousPageClick = useCallback(() => {
if (userSettings.libraryPageSize(undefined) > 0) { if (query.Limit > 0) {
query.StartIndex = Math.max(0, query.StartIndex - query.Limit); query.StartIndex = Math.max(0, query.StartIndex - query.Limit);
} }
reloadItems(); reloadItems();
} }, [query, reloadItems]);
const pagingHtml = libraryBrowser.getQueryPagingHtml({
startIndex: query.StartIndex,
limit: query.Limit,
totalRecordCount: itemsResult.TotalRecordCount,
showLimit: false,
updatePageSizeSetting: false,
addLayoutButton: false,
sortButton: false,
filterButton: false
});
const paging = element.current?.querySelector('.paging') as HTMLDivElement;
paging.innerHTML = pagingHtml;
useEffect(() => {
const btnNextPage = element.current?.querySelector('.btnNextPage') as HTMLButtonElement; const btnNextPage = element.current?.querySelector('.btnNextPage') as HTMLButtonElement;
if (btnNextPage) { if (btnNextPage) {
if (startIndex + limit >= totalRecordCount) {
btnNextPage.disabled = true;
} else {
btnNextPage.disabled = false;
}
btnNextPage.addEventListener('click', onNextPageClick); btnNextPage.addEventListener('click', onNextPageClick);
} }
const btnPreviousPage = element.current?.querySelector('.btnPreviousPage') as HTMLButtonElement; const btnPreviousPage = element.current?.querySelector('.btnPreviousPage') as HTMLButtonElement;
if (btnPreviousPage) { if (btnPreviousPage) {
if (startIndex) {
btnPreviousPage.disabled = false;
} else {
btnPreviousPage.disabled = true;
}
btnPreviousPage.addEventListener('click', onPreviousPageClick); btnPreviousPage.addEventListener('click', onPreviousPageClick);
} }
}, [itemsResult, query, reloadItems]); }, [totalRecordCount, onNextPageClick, onPreviousPageClick, limit, startIndex]);
return ( return (
<div ref={element}> <div ref={element}>
<div className='paging' /> <div className='paging'>
{showControls && (
<div className='listPaging' style={{ display: 'flex', alignItems: 'center' }}>
<span>
{globalize.translate('ListPaging', (totalRecordCount ? startIndex + 1 : 0), recordsEnd, totalRecordCount)}
</span>
<IconButtonElement
is='paper-icon-button-light'
className='btnPreviousPage autoSize'
icon='material-icons arrow_back'
/>
<IconButtonElement
is='paper-icon-button-light'
className='btnNextPage autoSize'
icon='material-icons arrow_forward'
/>
</div>
)}
</div>
</div> </div>
); );
}; };

View file

@ -8,11 +8,11 @@ import { IQuery } from './type';
type SelectViewProps = { type SelectViewProps = {
getCurrentViewStyle: () => string; getCurrentViewStyle: () => string;
query: IQuery; query: IQuery;
savedViewKey: string; getViewSettings: () => string;
reloadItems: () => void; reloadItems: () => void;
} }
const SelectView: FunctionComponent<SelectViewProps> = ({ getCurrentViewStyle, savedViewKey, query, reloadItems }: SelectViewProps) => { const SelectView: FunctionComponent<SelectViewProps> = ({ getCurrentViewStyle, getViewSettings, query, reloadItems }: SelectViewProps) => {
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
@ -22,11 +22,11 @@ const SelectView: FunctionComponent<SelectViewProps> = ({ getCurrentViewStyle, s
}); });
btnSelectView.addEventListener('layoutchange', (e) => { btnSelectView.addEventListener('layoutchange', (e) => {
const viewStyle = (e as CustomEvent).detail.viewStyle; const viewStyle = (e as CustomEvent).detail.viewStyle;
userSettings.set(savedViewKey, viewStyle, false); userSettings.set(getViewSettings(), viewStyle, false);
query.StartIndex = 0; query.StartIndex = 0;
reloadItems(); reloadItems();
}); });
}, [getCurrentViewStyle, query, reloadItems, savedViewKey]); }, [getCurrentViewStyle, query, reloadItems, getViewSettings]);
return ( return (
<div ref={element}> <div ref={element}>

View file

@ -22,8 +22,7 @@ const Shuffle: FunctionComponent<ShuffleProps> = ({ itemsResult = {}, topParentI
}, [topParentId]); }, [topParentId]);
useEffect(() => { useEffect(() => {
const btnShuffle = element.current?.querySelector('.btnShuffle') as HTMLButtonElement; const btnShuffle = element.current?.querySelector('.btnShuffle');
btnShuffle.classList.toggle('hide', typeof itemsResult.TotalRecordCount === 'number' && itemsResult.TotalRecordCount < 1);
if (btnShuffle) { if (btnShuffle) {
btnShuffle.addEventListener('click', shuffle); btnShuffle.addEventListener('click', shuffle);
} }
@ -33,7 +32,7 @@ const Shuffle: FunctionComponent<ShuffleProps> = ({ itemsResult = {}, topParentI
<div ref={element}> <div ref={element}>
<IconButtonElement <IconButtonElement
is='paper-icon-button-light' is='paper-icon-button-light'
className='btnShuffle autoSize hide' className='btnShuffle autoSize'
title='Shuffle' title='Shuffle'
icon='material-icons shuffle' icon='material-icons shuffle'
/> />

View file

@ -5,13 +5,16 @@ import * as userSettings from '../../scripts/settings/userSettings';
import { IQuery } from './type'; import { IQuery } from './type';
type SortProps = { type SortProps = {
sortMenuOptions: () => { name: string; id: string}[]; getSortMenuOptions: () => {
name: string;
id: string;
}[];
query: IQuery; query: IQuery;
savedQueryKey: string; getSettingsKey: () => string;
reloadItems: () => void; reloadItems: () => void;
} }
const Sort: FunctionComponent<SortProps> = ({ sortMenuOptions, query, savedQueryKey, reloadItems }: SortProps) => { const Sort: FunctionComponent<SortProps> = ({ getSortMenuOptions, query, getSettingsKey, reloadItems }: SortProps) => {
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
@ -20,10 +23,10 @@ const Sort: FunctionComponent<SortProps> = ({ sortMenuOptions, query, savedQuery
if (btnSort) { if (btnSort) {
btnSort.addEventListener('click', (e) => { btnSort.addEventListener('click', (e) => {
libraryBrowser.showSortMenu({ libraryBrowser.showSortMenu({
items: sortMenuOptions(), items: getSortMenuOptions(),
callback: () => { callback: () => {
query.StartIndex = 0; query.StartIndex = 0;
userSettings.saveQuerySettings(savedQueryKey, query); userSettings.saveQuerySettings(getSettingsKey(), query);
reloadItems(); reloadItems();
}, },
query: query, query: query,
@ -31,7 +34,7 @@ const Sort: FunctionComponent<SortProps> = ({ sortMenuOptions, query, savedQuery
}); });
}); });
} }
}, [sortMenuOptions, query, reloadItems, savedQueryKey]); }, [getSortMenuOptions, query, reloadItems, getSettingsKey]);
return ( return (
<div ref={element}> <div ref={element}>

View file

@ -0,0 +1,144 @@
import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
import * as userSettings from '../../scripts/settings/userSettings';
import AlphaPickerContainer from './AlphaPickerContainer';
import Filter from './Filter';
import ItemsContainer from './ItemsContainer';
import Pagination from './Pagination';
import SelectView from './SelectView';
import Shuffle from './Shuffle';
import Sort from './Sort';
import { IQuery } from './type';
import NewCollection from './NewCollection';
type IProps = {
topParentId: string | null;
isBtnShuffleEnabled?: boolean;
isBtnFilterEnabled?: boolean;
isBtnNewCollectionEnabled?: boolean;
isAlphaPickerEnabled?: boolean;
getBasekey: () => string;
getFilterMode: () => string;
getItemTypes: () => string;
getSortMenuOptions: () => {
name: string;
id: string;
}[];
getNoItemsMessage: () => string;
}
const ViewItemsContainer: FunctionComponent<IProps> = ({
topParentId,
isBtnShuffleEnabled = false,
isBtnFilterEnabled = true,
isBtnNewCollectionEnabled = false,
isAlphaPickerEnabled = true,
getBasekey,
getFilterMode,
getItemTypes,
getSortMenuOptions,
getNoItemsMessage
}: IProps) => {
const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>({});
const element = useRef<HTMLDivElement>(null);
const getSettingsKey = useCallback(() => {
return `${topParentId} - ${getBasekey()}`;
}, [getBasekey, topParentId]);
const getViewSettings = useCallback(() => {
return `${getSettingsKey()} -view`;
}, [getSettingsKey]);
let query = useMemo<IQuery>(() => ({
SortBy: 'SortName,ProductionYear',
SortOrder: 'Ascending',
IncludeItemTypes: getItemTypes(),
Recursive: true,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
Limit: userSettings.libraryPageSize(undefined),
StartIndex: 0,
ParentId: topParentId
}), [getItemTypes, topParentId]);
if (getBasekey() === 'favorites') {
query.IsFavorite = true;
}
query = userSettings.loadQuerySettings(getSettingsKey(), query);
const getCurrentViewStyle = useCallback(() => {
return userSettings.get(getViewSettings(), false) || 'Poster';
}, [getViewSettings]);
const getContext = useCallback(() => {
const itemType = getItemTypes();
if (itemType === 'Movie' || itemType === 'BoxSet') {
return 'movies';
}
return null;
}, [getItemTypes]);
const reloadItems = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show();
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result);
window.scrollTo(0, 0);
loading.hide();
import('../../components/autoFocuser').then(({ default: autoFocuser }) => {
autoFocuser.autoFocus(page);
});
});
}, [query]);
useEffect(() => {
reloadItems();
}, [reloadItems]);
return (
<div ref={element}>
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} />
{isBtnShuffleEnabled && <Shuffle itemsResult={itemsResult} topParentId={topParentId} />}
<SelectView getCurrentViewStyle={getCurrentViewStyle} getViewSettings={getViewSettings} query={query} reloadItems={reloadItems} />
<Sort getSortMenuOptions={getSortMenuOptions} query={query} getSettingsKey={getSettingsKey} reloadItems={reloadItems} />
{isBtnFilterEnabled && <Filter query={query} getFilterMode={getFilterMode} reloadItems={reloadItems} />}
{isBtnNewCollectionEnabled && <NewCollection />}
</div>
{isAlphaPickerEnabled && <AlphaPickerContainer query={query} reloadItems={reloadItems} />}
<ItemsContainer
getCurrentViewStyle={getCurrentViewStyle}
query={query}
getContext={getContext}
items={itemsResult?.Items}
noItemsMessage={getNoItemsMessage()}
/>
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} />
</div>
</div>
);
};
export default ViewItemsContainer;

View file

@ -5,6 +5,7 @@ export type IQuery = {
Recursive?: boolean; Recursive?: boolean;
Fields?: string; Fields?: string;
ImageTypeLimit?: number; ImageTypeLimit?: number;
EnableTotalRecordCount?: boolean;
EnableImageTypes?: string; EnableImageTypes?: string;
StartIndex: number; StartIndex: number;
ParentId?: string | null; ParentId?: string | null;

View file

@ -1,19 +1,30 @@
import '../../elements/emby-itemscontainer/emby-itemscontainer'; import React, { FunctionComponent, useCallback } from 'react';
import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import * as userSettings from '../../scripts/settings/userSettings'; import ViewItemsContainer from '../components/ViewItemsContainer';
import ItemsContainer from '../components/ItemsContainer';
import NewCollection from '../components/NewCollection';
import Pagination from '../components/Pagination';
import SelectView from '../components/SelectView';
import Sort from '../components/Sort';
import { IQuery } from '../components/type';
const SortMenuOptions = () => { type IProps = {
topParentId: string | null;
}
const CollectionsView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const getBasekey = useCallback(() => {
return 'collections';
}, []);
const getFilterMode = useCallback(() => {
return 'movies';
}, []);
const getItemTypes = useCallback(() => {
return 'BoxSet';
}, []);
const getNoItemsMessage = useCallback(() => {
return 'MessageNoCollectionsAvailable';
}, []);
const getSortMenuOptions = useCallback(() => {
return [{ return [{
name: globalize.translate('Name'), name: globalize.translate('Name'),
id: 'SortName' id: 'SortName'
@ -21,79 +32,20 @@ const SortMenuOptions = () => {
name: globalize.translate('OptionDateAdded'), name: globalize.translate('OptionDateAdded'),
id: 'DateCreated,SortName' id: 'DateCreated,SortName'
}]; }];
}; }, []);
type IProps = {
topParentId: string | null;
}
const CollectionsView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const savedQueryKey = topParentId + '-moviecollections';
const savedViewKey = savedQueryKey + '-view';
const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>({});
const element = useRef<HTMLDivElement>(null);
const query = useMemo<IQuery>(() => ({
SortBy: 'SortName',
SortOrder: 'Ascending',
IncludeItemTypes: 'BoxSet',
Recursive: true,
Fields: 'PrimaryImageAspectRatio,SortName',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
Limit: userSettings.libraryPageSize(undefined),
StartIndex: 0,
ParentId: topParentId }), [topParentId]);
userSettings.loadQuerySettings(savedQueryKey, query);
const getCurrentViewStyle = useCallback(() => {
return userSettings.get(savedViewKey, false) || 'Poster';
}, [savedViewKey]);
const reloadItems = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show();
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result);
window.scrollTo(0, 0);
loading.hide();
import('../../components/autoFocuser').then(({ default: autoFocuser }) => {
autoFocuser.autoFocus(page);
});
});
}, [query]);
useEffect(() => {
reloadItems();
}, [reloadItems]);
return ( return (
<div ref={element}> <ViewItemsContainer
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'> topParentId={topParentId}
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} /> isBtnFilterEnabled={false}
isBtnNewCollectionEnabled={true}
<SelectView getCurrentViewStyle={getCurrentViewStyle} savedViewKey={savedViewKey} query={query} reloadItems={reloadItems} /> isAlphaPickerEnabled={false}
<Sort sortMenuOptions={SortMenuOptions} query={query} savedQueryKey={savedQueryKey} reloadItems={reloadItems} /> getBasekey={getBasekey}
<NewCollection /> getFilterMode={getFilterMode}
getItemTypes={getItemTypes}
</div> getSortMenuOptions={getSortMenuOptions}
getNoItemsMessage={getNoItemsMessage}
<ItemsContainer getCurrentViewStyle={getCurrentViewStyle} query={query} items={itemsResult?.Items} noItemsMessage= 'MessageNoCollectionsAvailable' /> />
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} />
</div>
</div>
); );
}; };

View file

@ -1,22 +1,30 @@
import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client'; import React, { FunctionComponent, useCallback } from 'react';
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import * as userSettings from '../../scripts/settings/userSettings'; import ViewItemsContainer from '../components/ViewItemsContainer';
import AlphaPickerContainer from '../components/AlphaPickerContainer';
import Filter from '../components/Filter';
import ItemsContainer from '../components/ItemsContainer';
import Pagination from '../components/Pagination';
import SelectView from '../components/SelectView';
import Sort from '../components/Sort';
import { IQuery } from '../components/type';
type IProps = { type IProps = {
topParentId: string | null; topParentId: string | null;
} }
const SortMenuOptions = () => { const FavoritesView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const getBasekey = useCallback(() => {
return 'favorites';
}, []);
const getFilterMode = useCallback(() => {
return 'movies';
}, []);
const getItemTypes = useCallback(() => {
return 'Movie';
}, []);
const getNoItemsMessage = useCallback(() => {
return 'MessageNoFavoritesAvailable';
}, []);
const getSortMenuOptions = useCallback(() => {
return [{ return [{
name: globalize.translate('Name'), name: globalize.translate('Name'),
id: 'SortName,ProductionYear' id: 'SortName,ProductionYear'
@ -48,77 +56,17 @@ const SortMenuOptions = () => {
name: globalize.translate('Runtime'), name: globalize.translate('Runtime'),
id: 'Runtime,SortName,ProductionYear' id: 'Runtime,SortName,ProductionYear'
}]; }];
}; }, []);
const FavoritesView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const savedQueryKey = topParentId + '-favorites';
const savedViewKey = savedQueryKey + '-view';
const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>({});
const element = useRef<HTMLDivElement>(null);
const query = useMemo<IQuery>(() => ({
SortBy: 'SortName,ProductionYear',
SortOrder: 'Ascending',
IncludeItemTypes: 'Movie',
Recursive: true,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
Limit: userSettings.libraryPageSize(undefined),
IsFavorite: true,
StartIndex: 0,
ParentId: topParentId }), [topParentId]);
userSettings.loadQuerySettings(savedQueryKey, query);
const getCurrentViewStyle = useCallback(() => {
return userSettings.get(savedViewKey, false) || 'Poster';
}, [savedViewKey]);
const reloadItems = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show();
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result);
window.scrollTo(0, 0);
loading.hide();
import('../../components/autoFocuser').then(({ default: autoFocuser }) => {
autoFocuser.autoFocus(page);
});
});
}, [query]);
useEffect(() => {
reloadItems();
}, [query, reloadItems]);
return ( return (
<div ref={element}> <ViewItemsContainer
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'> topParentId={topParentId}
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} /> getBasekey={getBasekey}
getFilterMode={getFilterMode}
<SelectView getCurrentViewStyle={getCurrentViewStyle} savedViewKey={savedViewKey} query={query} reloadItems={reloadItems} /> getItemTypes={getItemTypes}
<Sort sortMenuOptions={SortMenuOptions} query={query} savedQueryKey={savedQueryKey} reloadItems={reloadItems} /> getSortMenuOptions={getSortMenuOptions}
<Filter query={query} reloadItems={reloadItems} /> getNoItemsMessage={getNoItemsMessage}
/>
</div>
<AlphaPickerContainer query={query} reloadItems={reloadItems} />
<ItemsContainer getCurrentViewStyle={getCurrentViewStyle} query={query} items={itemsResult?.Items} noItemsMessage= 'MessageNoFavoritesAvailable' />
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} />
</div>
</div>
); );
}; };

View file

@ -11,13 +11,18 @@ type IProps = {
} }
const GenresView: FunctionComponent<IProps> = ({ topParentId }: IProps) => { const GenresView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const savedQueryKey = topParentId + '-moviegenres';
const savedViewKey = savedQueryKey + '-view';
const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>({}); const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>({});
const element = useRef<HTMLDivElement>(null); const element = useRef<HTMLDivElement>(null);
const query = useMemo<IQuery>(() => ({ const getSettingsKey = useCallback(() => {
return topParentId + '-genres';
}, [topParentId]);
const getViewSettings = useCallback(() => {
return getSettingsKey() + '-view';
}, [getSettingsKey]);
let query = useMemo<IQuery>(() => ({
SortBy: 'SortName', SortBy: 'SortName',
SortOrder: 'Ascending', SortOrder: 'Ascending',
IncludeItemTypes: 'Movie', IncludeItemTypes: 'Movie',
@ -27,20 +32,13 @@ const GenresView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
StartIndex: 0, StartIndex: 0,
ParentId: topParentId }), [topParentId]); ParentId: topParentId }), [topParentId]);
userSettings.loadQuerySettings(savedQueryKey, query); query = userSettings.loadQuerySettings(getSettingsKey(), query);
const getCurrentViewStyle = useCallback(() => { const getCurrentViewStyle = useCallback(() => {
return userSettings.get(savedViewKey, false) || 'Poster'; return userSettings.get(getViewSettings(), false) || 'Poster';
}, [savedViewKey]); }, [getViewSettings]);
const reloadItems = useCallback(() => { const reloadItems = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show(); loading.show();
window.ApiClient.getGenres(window.ApiClient.getCurrentUserId(), query).then((result) => { window.ApiClient.getGenres(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result); setItemsResult(result);

View file

@ -1,23 +1,30 @@
import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client'; import React, { FunctionComponent, useCallback } from 'react';
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import * as userSettings from '../../scripts/settings/userSettings';
import AlphaPickerContainer from '../components/AlphaPickerContainer'; import ViewItemsContainer from '../components/ViewItemsContainer';
import Filter from '../components/Filter';
import ItemsContainer from '../components/ItemsContainer';
import Pagination from '../components/Pagination';
import SelectView from '../components/SelectView';
import Shuffle from '../components/Shuffle';
import Sort from '../components/Sort';
import { IQuery } from '../components/type';
type IProps = { type IProps = {
topParentId: string | null; topParentId: string | null;
} }
const SortMenuOptions = () => { const MoviesView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const getBasekey = useCallback(() => {
return 'movies';
}, []);
const getFilterMode = useCallback(() => {
return 'movies';
}, []);
const getItemTypes = useCallback(() => {
return 'Movie';
}, []);
const getNoItemsMessage = useCallback(() => {
return 'MessageNoItemsAvailable';
}, []);
const getSortMenuOptions = useCallback(() => {
return [{ return [{
name: globalize.translate('Name'), name: globalize.translate('Name'),
id: 'SortName,ProductionYear' id: 'SortName,ProductionYear'
@ -49,79 +56,18 @@ const SortMenuOptions = () => {
name: globalize.translate('Runtime'), name: globalize.translate('Runtime'),
id: 'Runtime,SortName,ProductionYear' id: 'Runtime,SortName,ProductionYear'
}]; }];
}; }, []);
const MoviesView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const savedQueryKey = topParentId + '-movies';
const savedViewKey = savedQueryKey + '-view';
const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>();
const element = useRef<HTMLDivElement>(null);
const query = useMemo<IQuery>(() => ({
SortBy: 'SortName,ProductionYear',
SortOrder: 'Ascending',
IncludeItemTypes: 'Movie',
Recursive: true,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
Limit: userSettings.libraryPageSize(undefined),
StartIndex: 0,
ParentId: topParentId }), [topParentId]);
userSettings.loadQuerySettings(savedQueryKey, query);
const getCurrentViewStyle = useCallback(() => {
return userSettings.get(savedViewKey, false) || 'Poster';
}, [savedViewKey]);
const reloadItems = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show();
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result);
window.scrollTo(0, 0);
loading.hide();
import('../../components/autoFocuser').then(({ default: autoFocuser }) => {
autoFocuser.autoFocus(page);
});
});
}, [query]);
useEffect(() => {
reloadItems();
}, [query, reloadItems]);
return ( return (
<div ref={element}> <ViewItemsContainer
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'> topParentId={topParentId}
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} /> isBtnShuffleEnabled={true}
getBasekey={getBasekey}
<Shuffle itemsResult= {itemsResult} topParentId={topParentId} /> getFilterMode={getFilterMode}
getItemTypes={getItemTypes}
<SelectView getCurrentViewStyle={getCurrentViewStyle} savedViewKey={savedViewKey} query={query} reloadItems={reloadItems} /> getSortMenuOptions={getSortMenuOptions}
<Sort sortMenuOptions={SortMenuOptions} query={query} savedQueryKey={savedQueryKey} reloadItems={reloadItems} /> getNoItemsMessage={getNoItemsMessage}
<Filter query={query} reloadItems={reloadItems} /> />
</div>
<AlphaPickerContainer query={query} reloadItems={reloadItems} />
<ItemsContainer getCurrentViewStyle={getCurrentViewStyle} query={query} items={itemsResult?.Items} noItemsMessage= 'NoCreatedLibraries' />
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} />
</div>
</div>
); );
}; };

View file

@ -57,7 +57,7 @@ const SuggestionsView: FunctionComponent<IProps> = (props: IProps) => {
const loadResume = useCallback((page, userId, parentId) => { const loadResume = useCallback((page, userId, parentId) => {
loading.show(); loading.show();
const screenWidth: any = dom.getWindowSize(); const screenWidth = dom.getWindowSize();
const options = { const options = {
SortBy: 'DatePlayed', SortBy: 'DatePlayed',
SortOrder: 'Descending', SortOrder: 'Descending',
@ -82,7 +82,7 @@ const SuggestionsView: FunctionComponent<IProps> = (props: IProps) => {
}, [autoFocus]); }, [autoFocus]);
const loadSuggestions = useCallback((page, userId) => { const loadSuggestions = useCallback((page, userId) => {
const screenWidth: any = dom.getWindowSize(); const screenWidth = dom.getWindowSize();
let itemLimit = 5; let itemLimit = 5;
if (screenWidth.innerWidth >= 1600) { if (screenWidth.innerWidth >= 1600) {
itemLimit = 8; itemLimit = 8;

View file

@ -1,19 +1,31 @@
import '../../elements/emby-itemscontainer/emby-itemscontainer';
import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client'; import React, { FunctionComponent, useCallback } from 'react';
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import * as userSettings from '../../scripts/settings/userSettings'; import ViewItemsContainer from '../components/ViewItemsContainer';
import AlphaPickerContainer from '../components/AlphaPickerContainer';
import Filter from '../components/Filter';
import ItemsContainer from '../components/ItemsContainer';
import Pagination from '../components/Pagination';
import Sort from '../components/Sort';
import { IQuery } from '../components/type';
const SortMenuOptions = () => { type IProps = {
topParentId: string | null;
}
const TrailersView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const getBasekey = useCallback(() => {
return 'trailers';
}, []);
const getFilterMode = useCallback(() => {
return 'movies';
}, []);
const getItemTypes = useCallback(() => {
return 'Trailer';
}, []);
const getNoItemsMessage = useCallback(() => {
return 'MessageNoTrailersFound';
}, []);
const getSortMenuOptions = useCallback(() => {
return [{ return [{
name: globalize.translate('Name'), name: globalize.translate('Name'),
id: 'SortName' id: 'SortName'
@ -36,75 +48,17 @@ const SortMenuOptions = () => {
name: globalize.translate('OptionReleaseDate'), name: globalize.translate('OptionReleaseDate'),
id: 'PremiereDate,SortName' id: 'PremiereDate,SortName'
}]; }];
}; }, []);
type IProps = {
topParentId: string | null;
}
const TrailersView: FunctionComponent<IProps> = ({ topParentId }: IProps) => {
const savedQueryKey = topParentId + '-trailers';
const savedViewKey = savedQueryKey + '-view';
const [ itemsResult, setItemsResult ] = useState<BaseItemDtoQueryResult>();
const element = useRef<HTMLDivElement>(null);
const query = useMemo<IQuery>(() => ({
SortBy: 'SortName',
SortOrder: 'Ascending',
IncludeItemTypes: 'Trailer',
Recursive: true,
Fields: 'PrimaryImageAspectRatio,SortName,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
Limit: userSettings.libraryPageSize(undefined),
StartIndex: 0,
ParentId: topParentId }), [topParentId]);
userSettings.loadQuerySettings(savedQueryKey, query);
const getCurrentViewStyle = useCallback(() => {
return userSettings.get(savedViewKey, false) || 'Poster';
}, [savedViewKey]);
const reloadItems = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show();
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result);
window.scrollTo(0, 0);
loading.hide();
});
}, [query]);
useEffect(() => {
reloadItems();
}, [query, reloadItems]);
return ( return (
<div ref={element}> <ViewItemsContainer
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'> topParentId={topParentId}
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} /> getBasekey={getBasekey}
getFilterMode={getFilterMode}
<Sort sortMenuOptions={SortMenuOptions} query={query} savedQueryKey={savedQueryKey} reloadItems={reloadItems} /> getItemTypes={getItemTypes}
<Filter query={query} reloadItems={reloadItems} /> getSortMenuOptions={getSortMenuOptions}
getNoItemsMessage={getNoItemsMessage}
</div> />
<AlphaPickerContainer query={query} reloadItems={reloadItems} />
<ItemsContainer getCurrentViewStyle={getCurrentViewStyle} query={query} items={itemsResult?.Items} noItemsMessage= 'MessageNoTrailersFound' />
<div className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
<Pagination itemsResult= {itemsResult} query={query} reloadItems={reloadItems} />
</div>
</div>
); );
}; };