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:
parent
2bf4113821
commit
9254dd2208
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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}`;
|
||||
|
Loading…
Reference in New Issue
Block a user