web/satellite/vuetify-poc: enable object browser pagination

Enabled object browser pagination for vuetify app.
Also fixed some small bug when returning to first page.

Issue:
https://github.com/storj/storj/issues/5595

Change-Id: I8b5e90a4cd7d7a79a8beeb292b7374db3f93d700
This commit is contained in:
Vitalii 2023-09-07 17:14:25 +03:00 committed by Storj Robot
parent 2bf4113821
commit 9254dd2208
4 changed files with 79 additions and 13 deletions

View File

@ -458,7 +458,7 @@ function changePageAndLimit(page: number, limit: number): void {
const tokenToBeFetched = obStore.state.continuationTokens.get(tokenKey);
if (!tokenToBeFetched) {
obStore.listByToken(routePath.value, 1, tokenToBeFetched);
obStore.initList(routePath.value);
return;
}

View File

@ -292,6 +292,8 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
const { Contents, CommonPrefixes } = response;
processFetchedObjects(path, Contents, CommonPrefixes);
state.activeObjectsRange = { start: 1, end: MAX_KEY_COUNT };
}
keyCount += response.KeyCount ?? 0;
@ -305,7 +307,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
state.totalObjectCount = keyCount;
}
async function listByToken(path: string, key: number, continuationToken?: string): Promise<void> {
async function listByToken(path: string, key: number, continuationToken: string): Promise<void> {
assertIsInitialized(state);
const input: ListObjectsV2CommandInput = {
@ -321,10 +323,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
processFetchedObjects(path, Contents, CommonPrefixes);
state.activeObjectsRange = {
start: key === 1 ? key : key - MAX_KEY_COUNT,
end: key === 1 ? MAX_KEY_COUNT : key,
};
state.activeObjectsRange = { start: key - MAX_KEY_COUNT, end: key };
}
function processFetchedObjects(path: string, Contents: _Object[] | undefined, CommonPrefixes: CommonPrefix[] | undefined): void {

View File

@ -43,14 +43,14 @@ export type UUID = string
export type MemorySize = string
export type Time = string
export function tableSizeOptions(itemCount: number): {title: string, value: number}[] {
export function tableSizeOptions(itemCount: number, isObjectBrowser = false): {title: string, value: number}[] {
const opts = [
{ title: '10', value: 10 },
{ title: '25', value: 25 },
{ title: '50', value: 50 },
{ title: '100', value: 100 },
];
if (itemCount < 1000) {
if (itemCount < 1000 && !isObjectBrowser) {
return [{ title: 'All', value: itemCount }, ...opts];
}
return opts;

View File

@ -30,7 +30,10 @@
hover
must-sort
:loading="isFetching || loading"
:items-length="allFiles.length"
:items-length="isPaginationEnabled ? totalObjectCount : allFiles.length"
:items-per-page-options="isPaginationEnabled ? tableSizeOptions(totalObjectCount, true) : undefined"
@update:page="onPageChange"
@update:itemsPerPage="onLimitChange"
>
<template #item.name="{ item }: ItemSlotProps">
<v-btn
@ -77,13 +80,20 @@ import {
} from 'vuetify/components';
import { VDataTableServer } from 'vuetify/labs/components';
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
import {
BrowserObject,
MAX_KEY_COUNT,
ObjectBrowserCursor,
useObjectBrowserStore,
} from '@/store/modules/objectBrowserStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { useNotify } from '@/utils/hooks';
import { SHORT_MONTHS_NAMES } from '@/utils/constants/date';
import { Size } from '@/utils/bytesSize';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useBucketsStore } from '@/store/modules/bucketsStore';
import { useConfigStore } from '@/store/modules/configStore';
import { tableSizeOptions } from '@/types/common';
import BrowserRowActions from '@poc/components/BrowserRowActions.vue';
import FilePreviewDialog from '@poc/components/dialogs/FilePreviewDialog.vue';
@ -131,6 +141,7 @@ const props = defineProps<{
loading?: boolean;
}>();
const config = useConfigStore();
const obStore = useObjectBrowserStore();
const projectsStore = useProjectsStore();
const bucketsStore = useBucketsStore();
@ -180,12 +191,29 @@ const bucketName = computed<string>(() => bucketsStore.state.fileComponentBucket
*/
const filePath = computed<string>(() => bucketsStore.state.fileComponentPath);
/**
* Returns total object count from store.
*/
const isPaginationEnabled = computed<boolean>(() => config.state.config.objectBrowserPaginationEnabled);
/**
* Returns total object count from store.
*/
const totalObjectCount = computed<number>(() => obStore.state.totalObjectCount);
/**
* Returns table cursor from store.
*/
const cursor = computed<ObjectBrowserCursor>(() => obStore.state.cursor);
/**
* Returns every file under the current path.
*/
const allFiles = computed<BrowserObjectWrapper[]>(() => {
if (props.forceEmpty) return [];
return obStore.state.files.map<BrowserObjectWrapper>(file => {
const objects = isPaginationEnabled.value ? obStore.displayedObjects : obStore.state.files;
return objects.map<BrowserObjectWrapper>(file => {
const lowerName = file.Key.toLowerCase();
const dotIdx = lowerName.indexOf('.');
const ext = dotIdx === -1 ? '' : file.Key.slice(dotIdx + 1);
@ -243,11 +271,43 @@ const tableFiles = computed<BrowserObjectWrapper[]>(() => {
});
}
if (opts.itemsPerPage === -1) return files;
if (opts.itemsPerPage === -1 || isPaginationEnabled.value) return files;
return files.slice((opts.page - 1) * opts.itemsPerPage, opts.page * opts.itemsPerPage);
});
/**
* Handles page change event.
*/
function onPageChange(page: number): void {
obStore.setCursor({ page, limit: options.value?.itemsPerPage ?? 10 });
const lastObjectOnPage = page * cursor.value.limit;
const activeRange = obStore.state.activeObjectsRange;
if (lastObjectOnPage > activeRange.start && lastObjectOnPage <= activeRange.end) {
return;
}
const path = filePath.value ? filePath.value + '/' : '';
const tokenKey = Math.ceil(lastObjectOnPage / MAX_KEY_COUNT) * MAX_KEY_COUNT;
const tokenToBeFetched = obStore.state.continuationTokens.get(tokenKey);
if (!tokenToBeFetched) {
obStore.initList(path);
return;
}
obStore.listByToken(path, tokenKey, tokenToBeFetched);
}
/**
* Handles items per page change event.
*/
function onLimitChange(newLimit: number): void {
obStore.setCursor({ page: options.value?.page ?? 1, limit: newLimit });
}
/**
* Returns the string form of the file's last modified date.
*/
@ -308,7 +368,14 @@ async function fetchFiles(): Promise<void> {
isFetching.value = true;
try {
await obStore.list(filePath.value ? filePath.value + '/' : '');
const path = filePath.value ? filePath.value + '/' : '';
if (isPaginationEnabled.value) {
await obStore.initList(path);
} else {
await obStore.list(path);
}
selected.value = [];
} catch (err) {
err.message = `Error fetching files. ${err.message}`;