web/satellite: add loader to object browser table
This is a fix based on early feedback from QA team. Added loader to object browser table so that user can't change pages while request is still in progress because it breaks pagination. Change-Id: I5cc2ff057955478b3c745c169d520e1a639eff92
This commit is contained in:
parent
bd48a5cbe6
commit
92a69c7de4
@ -111,6 +111,7 @@
|
||||
:total-page-count="isPaginationEnabled ? pageCount : 0"
|
||||
:total-items-count="isPaginationEnabled ? fetchedObjectsCount : files.length"
|
||||
show-select
|
||||
:loading="isLoading"
|
||||
class="file-browser-table"
|
||||
:on-page-change="isPaginationEnabled ? changePageAndLimit : null"
|
||||
@selectAllClicked="toggleSelectAllFiles"
|
||||
@ -193,7 +194,7 @@
|
||||
</template>
|
||||
</v-table>
|
||||
<div
|
||||
v-if="!fetchingFilesSpinner"
|
||||
v-if="!isLoading"
|
||||
class="upload-help"
|
||||
@click="buttonFileUpload"
|
||||
>
|
||||
@ -202,12 +203,6 @@
|
||||
Drop Files Here to Upload
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<div class="spinner-border" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -239,6 +234,7 @@ import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useConfigStore } from '@/store/modules/configStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { DEFAULT_PAGE_LIMIT } from '@/types/pagination';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import BucketSettingsNav from '@/components/objects/BucketSettingsNav.vue';
|
||||
@ -261,11 +257,11 @@ const analyticsStore = useAnalyticsStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const notify = useNotify();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
|
||||
const folderInput = ref<HTMLInputElement>();
|
||||
const fileInput = ref<HTMLInputElement>();
|
||||
|
||||
const fetchingFilesSpinner = ref<boolean>(false);
|
||||
const isUploadDropDownShown = ref<boolean>(false);
|
||||
const isLockedBanner = ref<boolean>(true);
|
||||
const isTooManyObjectsBanner = ref<boolean>(true);
|
||||
@ -363,7 +359,7 @@ const objectsCount = computed((): number => {
|
||||
const lockedFilesEntryDisplayed = computed((): boolean => {
|
||||
return lockedFilesCount.value > 0 &&
|
||||
objectsCount.value <= NUMBER_OF_DISPLAYED_OBJECTS &&
|
||||
!fetchingFilesSpinner.value &&
|
||||
!isLoading.value &&
|
||||
!currentPath.value;
|
||||
});
|
||||
|
||||
@ -444,7 +440,7 @@ const bucket = computed((): string => {
|
||||
/**
|
||||
* Changes table page and limit.
|
||||
*/
|
||||
function changePageAndLimit(page: number, limit: number): void {
|
||||
async function changePageAndLimit(page: number, limit: number): void {
|
||||
obStore.setCursor({ limit, page });
|
||||
|
||||
const lastObjectOnPage = page * limit;
|
||||
@ -454,15 +450,17 @@ function changePageAndLimit(page: number, limit: number): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const tokenKey = Math.ceil(lastObjectOnPage / MAX_KEY_COUNT) * MAX_KEY_COUNT;
|
||||
await withLoading(async () => {
|
||||
const tokenKey = Math.ceil(lastObjectOnPage / MAX_KEY_COUNT) * MAX_KEY_COUNT;
|
||||
|
||||
const tokenToBeFetched = obStore.state.continuationTokens.get(tokenKey);
|
||||
if (!tokenToBeFetched) {
|
||||
obStore.initList(routePath.value);
|
||||
return;
|
||||
}
|
||||
const tokenToBeFetched = obStore.state.continuationTokens.get(tokenKey);
|
||||
if (!tokenToBeFetched) {
|
||||
await obStore.initList(routePath.value);
|
||||
return;
|
||||
}
|
||||
|
||||
obStore.listByToken(routePath.value, tokenKey, tokenToBeFetched);
|
||||
await obStore.listByToken(routePath.value, tokenKey, tokenToBeFetched);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -496,11 +494,13 @@ async function onRouteChange(): Promise<void> {
|
||||
routePath.value = calculateRoutePath();
|
||||
obStore.closeDropdown();
|
||||
|
||||
if (isPaginationEnabled.value) {
|
||||
await obStore.initList(routePath.value);
|
||||
} else {
|
||||
await list(routePath.value);
|
||||
}
|
||||
await withLoading(async () => {
|
||||
if (isPaginationEnabled.value) {
|
||||
await obStore.initList(routePath.value);
|
||||
} else {
|
||||
await list(routePath.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -653,24 +653,20 @@ onBeforeMount(async () => {
|
||||
// clear previous file selections.
|
||||
obStore.clearAllSelectedFiles();
|
||||
|
||||
// display the spinner while files are being fetched
|
||||
fetchingFilesSpinner.value = true;
|
||||
|
||||
try {
|
||||
if (isPaginationEnabled.value) {
|
||||
await obStore.initList('');
|
||||
} else {
|
||||
await Promise.all([
|
||||
list(''),
|
||||
obStore.getObjectCount(),
|
||||
]);
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
if (isPaginationEnabled.value) {
|
||||
await obStore.initList('');
|
||||
} else {
|
||||
await Promise.all([
|
||||
list(''),
|
||||
obStore.getObjectCount(),
|
||||
]);
|
||||
}
|
||||
} catch (err) {
|
||||
notify.error(err.message, AnalyticsErrorEventSource.FILE_BROWSER_LIST_CALL);
|
||||
}
|
||||
} catch (err) {
|
||||
notify.error(err.message, AnalyticsErrorEventSource.FILE_BROWSER_LIST_CALL);
|
||||
}
|
||||
|
||||
// remove the spinner after files have been fetched
|
||||
fetchingFilesSpinner.value = false;
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
|
@ -10,7 +10,7 @@
|
||||
<span v-else class="size-changer__selector__content__label">Size</span>
|
||||
<arrow-down-icon class="size-changer__selector__content__arrow" :class="{ open: isOpen }" />
|
||||
</div>
|
||||
<div v-if="isOpen" v-click-outside="closeSelector" class="size-changer__selector__dropdown">
|
||||
<div v-if="isOpen" v-click-outside="closeSelector" class="size-changer__selector__dropdown" :class="{ 'custom-top': !withAllOption }">
|
||||
<div
|
||||
v-for="(option, index) in options"
|
||||
:key="index"
|
||||
@ -54,12 +54,16 @@ const options = computed((): {label:string, value:number}[] => {
|
||||
{ label: '50', value: 50 },
|
||||
{ label: '100', value: 100 },
|
||||
];
|
||||
if (props.itemCount && props.itemCount < 1000 && !props.simplePagination) {
|
||||
if (props.itemCount && withAllOption.value) {
|
||||
return [{ label: 'All', value: props.itemCount }, ...opts];
|
||||
}
|
||||
return opts;
|
||||
});
|
||||
|
||||
const withAllOption = computed<boolean>(() => {
|
||||
return props.itemCount !== undefined && props.itemCount < 1000 && !props.simplePagination;
|
||||
});
|
||||
|
||||
/**
|
||||
* whether the selector drop down is open
|
||||
* */
|
||||
@ -191,4 +195,8 @@ function toggleSelector() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-top {
|
||||
top: -150px;
|
||||
}
|
||||
</style>
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
<template>
|
||||
<div class="table-wrapper">
|
||||
<div v-if="loading" class="table-wrapper__loader">
|
||||
<VLoader width="100px" height="100px" />
|
||||
</div>
|
||||
<table class="base-table" border="0" cellpadding="0" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -38,6 +41,7 @@ import { PageChangeCallback } from '@/types/pagination';
|
||||
|
||||
import TablePagination from '@/components/common/TablePagination.vue';
|
||||
import VTableCheckbox from '@/components/common/VTableCheckbox.vue';
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
itemsLabel?: string,
|
||||
@ -52,6 +56,7 @@ const props = withDefaults(defineProps<{
|
||||
selected?: boolean,
|
||||
showSelect?: boolean,
|
||||
simplePagination?: boolean,
|
||||
loading?: boolean,
|
||||
}>(), {
|
||||
selectable: false,
|
||||
selected: false,
|
||||
@ -65,6 +70,7 @@ const props = withDefaults(defineProps<{
|
||||
onNextClicked: null,
|
||||
onPreviousClicked: null,
|
||||
onPageSizeChanged: null,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['selectAllClicked']);
|
||||
@ -74,6 +80,18 @@ const emit = defineEmits(['selectAllClicked']);
|
||||
.table-wrapper {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
position: relative;
|
||||
|
||||
&__loader {
|
||||
border-radius: 12px;
|
||||
z-index: 1;
|
||||
background-color: rgb(0 0 0 / 5%);
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.base-table {
|
||||
|
@ -8,7 +8,7 @@
|
||||
transition="fade-transition"
|
||||
:persistent="isLoading"
|
||||
>
|
||||
<v-card rounded="xlg" ref="innerContent">
|
||||
<v-card ref="innerContent" rounded="xlg">
|
||||
<v-card-item class="pl-7 py-4">
|
||||
<template #prepend>
|
||||
<v-sheet
|
||||
|
Loading…
Reference in New Issue
Block a user