Skip to content

Commit

Permalink
[ui-storagebrowser] adds pagination in file preview page (#3949)
Browse files Browse the repository at this point in the history
* fixes linting
* fixes the search bar disabled edge case
  • Loading branch information
ramprasadagarwal authored Jan 20, 2025
1 parent afcae4c commit e67d150
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 81 deletions.
12 changes: 10 additions & 2 deletions apps/filebrowser/src/filebrowser/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
MAX_CHUNK_SIZE_BYTES,
_can_inline_display,
_is_hdfs_superuser,
_massage_page,
_normalize_path,
extract_upload_data,
perform_upload_task,
Expand Down Expand Up @@ -209,6 +208,15 @@ def download(request):
return response


def _massage_page(page, paginator):
return {
'page_number': page.number,
'page_size': paginator.per_page,
'total_pages': paginator.num_pages,
'total_size': paginator.count
}


@api_error_handler
def listdir_paged(request):
"""
Expand Down Expand Up @@ -280,7 +288,7 @@ def listdir_paged(request):
response = {
'is_trash_enabled': is_trash_enabled,
'files': page.object_list if page else [],
'page': _massage_page(page, paginator) if page else {}, # TODO: Check if we need to clean response of _massage_page
'page': _massage_page(page, paginator) if page else {},
# TODO: Check what to keep or what to remove? or move some fields to /get_config?
'is_fs_superuser': is_fs_superuser,
'groups': is_fs_superuser and [str(x) for x in Group.objects.values_list('name', flat=True)] or [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,6 @@ const StorageDirectoryPage = ({
}
};

//pagination related functions handled by parent
const onPreviousPageButtonClicked = (previousPageNumber: number) => {
//If previous page does not exists api returns 0
setPageNumber(previousPageNumber === 0 ? 1 : previousPageNumber);
};

const onNextPageButtonClicked = (nextPageNumber: number, numPages: number) => {
//If next page does not exists api returns 0
setPageNumber(nextPageNumber === 0 ? numPages : nextPageNumber);
};

const handleSearch = useCallback(
useDebounce(searchTerm => {
setSearchTerm(encodeURIComponent(searchTerm));
Expand Down Expand Up @@ -290,6 +279,7 @@ const StorageDirectoryPage = ({
onChange={event => {
handleSearch(event.target.value);
}}
disabled={!tableData.length && !searchTerm.length}
/>
<div className="hue-storage-browser__actions-bar-right">
<StorageBrowserActions
Expand Down Expand Up @@ -333,13 +323,11 @@ const StorageDirectoryPage = ({
{...restProps}
/>

{filesData?.page && filesData?.page?.total_count > 0 && (
{filesData?.page && filesData?.page?.total_pages > 0 && (
<Pagination
onNextPageButtonClicked={onNextPageButtonClicked}
onPageNumberChange={setPageNumber}
onPageSizeChange={setPageSize}
onPreviousPageButtonClicked={onPreviousPageButtonClicked}
setPageSize={setPageSize}
pageSize={pageSize}
setPageNumber={setPageNumber}
pageStats={filesData?.page}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
flex: 1;
height: 100%;
flex-direction: column;
gap: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-s 0;
gap: vars.$fluidx-spacing-xs;
padding: vars.$fluidx-spacing-xs 0;

.meta-data {
display: flex;
gap: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-xs;
background-color: vars.$fluidx-gray-040;
border-radius: vars.$border-radius-base;
}
Expand All @@ -47,7 +47,6 @@
.meta-data__column {
display: flex;
flex-direction: column;

}

.meta-data__column-label {
Expand All @@ -64,14 +63,14 @@
.preview {
display: flex;
flex-direction: column;
flex: 1;
height: 100%;
}

.preview__title-bar {
display: flex;
justify-content: space-between;
gap: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-xs vars.$fluidx-spacing-s;
font-size: vars.$font-size-lg;
background-color: vars.$fluidx-gray-040;
color: vars.$fluidx-gray-700;
Expand All @@ -82,7 +81,7 @@

.preview__action-group {
display: flex;
gap: vars.$fluidx-spacing-s;
gap: vars.$fluidx-spacing-xs;
}

.preview__content {
Expand All @@ -98,7 +97,7 @@
height: 100%;
border: none;
border-radius: 0;
padding: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-xs vars.$fluidx-spacing-s;
box-shadow: none;
}

Expand All @@ -108,6 +107,14 @@
background-color: vars.$fluidx-white;
}

.preview__editable-file {
display: flex;
flex: 1;
height: 100%;
flex-direction: column;
justify-content: flex-end;
}

.preview__document {
display: flex;
align-items: center;
Expand All @@ -128,4 +135,4 @@
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import {
} from '../../../reactComponents/FileChooser/api';
import huePubSub from '../../../utils/huePubSub';
import useSaveData from '../../../utils/hooks/useSaveData';
import Pagination from '../../../reactComponents/Pagination/Pagination';
import {
DEFAULT_PREVIEW_PAGE_SIZE,
EDITABLE_FILE_FORMATS,
SUPPORTED_FILE_EXTENSIONS,
SupportedFileTypes
Expand All @@ -54,6 +56,9 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps

const [isEditing, setIsEditing] = useState<boolean>(false);
const [fileContent, setFileContent] = useState<FilePreview['contents']>();
const [pageNumber, setPageNumber] = useState<number>(1);
const pageSize = DEFAULT_PREVIEW_PAGE_SIZE;
const pageOffset = (pageNumber - 1) * pageSize;

const { loading: isSaving, save } = useSaveData(SAVE_FILE_API_URL);

Expand All @@ -62,13 +67,17 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
loading: loadingPreview,
error: errorPreview
} = useLoadData<FilePreview>(FILE_PREVIEW_API_URL, {
params: { path: fileStats.path },
params: {
path: fileStats.path,
offset: pageOffset,
length: pageSize
},
onSuccess: d => setFileContent(d.contents),
skip:
fileStats.path === '' ||
fileStats.path === undefined ||
fileStats?.type !== BrowserViewType.file ||
EDITABLE_FILE_FORMATS[fileType] === undefined
!EDITABLE_FILE_FORMATS.has(fileType)
});

const fileMetaData = useMemo(() => getFileMetaData(t, fileStats), [t, fileStats]);
Expand Down Expand Up @@ -112,8 +121,14 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
!isEditing &&
config?.storage_browser.max_file_editor_size &&
config?.storage_browser.max_file_editor_size > fileStats.size &&
EDITABLE_FILE_FORMATS[fileType] &&
fileData?.compression?.toLocaleLowerCase() === 'none';
EDITABLE_FILE_FORMATS.has(fileType);

const pageStats = {
page_number: pageNumber,
total_pages: Math.ceil(fileStats.size / pageSize),
page_size: 0,
total_size: 0
};

const errorConfig = [
{
Expand Down Expand Up @@ -192,12 +207,17 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps

<div className="preview__content">
{fileType === SupportedFileTypes.TEXT && (
<textarea
value={fileContent}
onChange={e => setFileContent(e.target.value)}
readOnly={!isEditing}
className="preview__textarea"
/>
<div className="preview__editable-file">
<textarea
value={fileContent}
onChange={e => setFileContent(e.target.value)}
readOnly={!isEditing}
className="preview__textarea"
/>
{!loadingPreview && pageStats.total_pages > 1 && (
<Pagination setPageNumber={setPageNumber} pageStats={pageStats} />
)}
</div>
)}

{fileType === SupportedFileTypes.IMAGE && <img src={filePreviewUrl} alt={fileName} />}
Expand Down
12 changes: 4 additions & 8 deletions desktop/core/src/desktop/js/reactComponents/FileChooser/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,14 @@ export interface StorageDirectoryTableData
}

export interface PageStats {
number: number;
num_pages: number;
previous_page_number: number;
next_page_number: number;
start_index: number;
end_index: number;
total_count: number;
page_number: number;
total_pages: number;
page_size: number;
total_size: number;
}

export interface FilePreview {
contents: string;
compression?: string;
end: number;
length: number;
mode: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
.antd.cuix {
.hue-pagination {
background-color: vars.$fluidx-gray-100;
padding: vars.$fluidx-spacing-s;
padding: vars.$fluidx-spacing-xs;
display: flex;
gap: vars.$fluidx-spacing-xxl;
justify-content: flex-end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,38 @@ import { PageStats } from '../FileChooser/types';
import './Pagination.scss';

interface PaginationProps {
onNextPageButtonClicked: (nextPageNumber: number, numPages: number) => void;
onPageNumberChange: (pageNumber: number) => void;
onPageSizeChange: (pageSize: number) => void;
onPreviousPageButtonClicked: (previousPageNumber: number) => void;
pageSize: number;
setPageNumber: (pageNumber: number) => void;
setPageSize?: (pageSize: number) => void;
pageSize?: number;
pageSizeOptions?: number[];
pageStats: PageStats;
showIndexes?: boolean;
}

const defaultProps = {
pageSizeOptions: [10, 50, 500, 1000]
};

const Pagination = ({
onNextPageButtonClicked,
onPageNumberChange,
onPageSizeChange,
onPreviousPageButtonClicked,
pageSize,
setPageNumber,
setPageSize,
pageSizeOptions = [],
pageStats
pageStats,
showIndexes = false
}: PaginationProps): JSX.Element => {
const { t } = i18nReact.useTranslation();

const currentPageSize = pageSize;
const startIndex = pageStats.page_size * (pageStats.page_number - 1) + 1;
const endIndex = Math.min(pageStats.page_size * pageStats.page_number, pageStats.total_size);

const pageSizeOptionsMenu: MenuProps['items'] = pageSizeOptions.map(option => {
return {
key: option,
label: (
<BorderlessButton
onClick={() => {
onPageSizeChange(option);
onPageNumberChange(1);
setPageSize && setPageSize(option);
setPageNumber(1);
}}
className="hue-pagination__page-size-menu-item-btn"
data-event={''}
Expand All @@ -74,45 +72,57 @@ const Pagination = ({

return (
<div className="hue-pagination">
<div className="hue-pagination__page-size-control">
{t('Rows per page: ')}
<Dropdown menu={{ items: pageSizeOptionsMenu }}>
<BorderlessButton
className="hue-pagination__page-size-menu-btn"
data-event={''}
icon={<DropdownIcon />}
iconPosition="right"
>
{currentPageSize}
</BorderlessButton>
</Dropdown>
</div>
{pageStats.page_size > 0 && (
<div className="hue-pagination__page-size-control">
{t('Rows per page: ')}
<Dropdown menu={{ items: pageSizeOptionsMenu }}>
<BorderlessButton
className="hue-pagination__page-size-menu-btn"
data-event={''}
icon={<DropdownIcon />}
iconPosition="right"
>
{pageStats.page_size}
</BorderlessButton>
</Dropdown>
</div>
)}
<div className="hue-pagination__rows-stats-display">
{pageStats.start_index} - {pageStats.end_index} of {pageStats.total_count}
{showIndexes
? `${startIndex} - ${endIndex} of ${pageStats.total_size}`
: `${pageStats.page_number} of ${pageStats.total_pages}`}
</div>
<div className="hue-pagination__control-buttons-panel">
<BorderlessButton
onClick={() => onPageNumberChange(1)}
onClick={() => setPageNumber(1)}
className="hue-pagination__control-button"
data-event={''}
disabled={pageStats.page_number === 1}
title={t('First Page')}
icon={<PageFirstIcon />}
/>
<BorderlessButton
onClick={() => onPreviousPageButtonClicked(pageStats.previous_page_number)}
onClick={() => setPageNumber(pageStats.page_number - 1)}
className="hue-pagination__control-button"
data-event={''}
disabled={pageStats.page_number === 1}
title={t('First Page')}
icon={<PagePreviousIcon />}
/>
<BorderlessButton
onClick={() => onNextPageButtonClicked(pageStats.next_page_number, pageStats.num_pages)}
onClick={() => setPageNumber(pageStats.page_number + 1)}
className="hue-pagination__control-button"
data-event={''}
disabled={pageStats.page_number === pageStats.total_pages}
title={t('Next Page')}
icon={<PageNextIcon />}
/>
<BorderlessButton
onClick={() => onPageNumberChange(pageStats.num_pages)}
onClick={() => setPageNumber(pageStats.total_pages)}
className="hue-pagination__control-button"
data-event={''}
disabled={pageStats.page_number === pageStats.total_pages}
title={t('Last Page')}
icon={<PageLastIcon />}
/>
</div>
Expand Down
Loading

0 comments on commit e67d150

Please sign in to comment.