web/satellite: wire up vuetify access page to backend

Added logic to list, sort, search and paginate access grants table for Vuetify POC

Change-Id: I215a9ad4f894b6ac985cb6a3059fdcf007e3d914
This commit is contained in:
Vitalii 2023-07-21 16:58:54 +03:00 committed by Storj Robot
parent 28711e30ad
commit 5db0fd8846
5 changed files with 124 additions and 58 deletions

View File

@ -244,7 +244,7 @@ async function onPageClick(index: number, limit: number): Promise<void> {
try {
await agStore.getAccessGrants(index, projectsStore.state.selectedProject.id, limit);
} catch (error) {
await notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
}
}
@ -332,7 +332,7 @@ onMounted(async () => {
await agStore.getAccessGrants(FIRST_PAGE, projectsStore.state.selectedProject.id);
areGrantsFetching.value = false;
} catch (error) {
await notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
}
});

View File

@ -65,6 +65,8 @@ export interface AccessGrantsApi {
export enum AccessGrantsOrderBy {
NAME = 1,
CREATED_AT,
name = 1,
createdAt = 2,
}
/**

View File

@ -4,6 +4,8 @@
export enum SortDirection {
ASCENDING = 1,
DESCENDING,
asc = 1,
desc = 2,
}
export enum OnboardingOS {
@ -40,3 +42,16 @@ export enum PricingPlanType {
export type UUID = string
export type MemorySize = string
export type Time = string
export function tableSizeOptions(itemCount: number): {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) {
return [{ title: 'All', value: itemCount }, ...opts];
}
return opts;
}

View File

@ -11,85 +11,134 @@
hide-details
/>
<v-data-table
<v-data-table-server
v-model="selected"
:sort-by="sortBy"
:headers="headers"
:items="accesses"
:search="search"
:items="page.accessGrants"
:loading="areGrantsFetching"
:items-length="page.totalCount"
:items-per-page-options="tableSizeOptions(page.totalCount)"
item-value="name"
select-strategy="all"
class="elevation-1"
show-select
hover
@update:itemsPerPage="onUpdateLimit"
@update:page="onUpdatePage"
@update:sortBy="onUpdateSortBy"
>
<template #item.name="{ item }">
<span class="font-weight-bold">
{{ item.raw.name }}
</span>
</template>
<template #item.status="{ item }">
<v-chip :color="item.raw.status == 'Active' ? 'success' : 'warning'" variant="tonal" size="small" rounded="xl" class="font-weight-bold">
{{ item.raw.status }}
</v-chip>
<template #item.createdAt="{ item }">
<span>
{{ item.raw.createdAt.toLocaleString() }}
</span>
</template>
</v-data-table>
</v-data-table-server>
</v-card>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { VCard, VTextField, VChip } from 'vuetify/components';
import { VDataTable } from 'vuetify/labs/components';
import { ref, watch, onMounted, computed } from 'vue';
import { VCard, VTextField } from 'vuetify/components';
import { VDataTableServer } from 'vuetify/labs/components';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { AccessGrantCursor, AccessGrantsOrderBy, AccessGrantsPage } from '@/types/accessGrants';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
import { useNotify } from '@/utils/hooks';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { DEFAULT_PAGE_LIMIT } from '@/types/pagination';
import { SortDirection, tableSizeOptions } from '@/types/common';
const agStore = useAccessGrantsStore();
const projectsStore = useProjectsStore();
const notify = useNotify();
const FIRST_PAGE = 1;
const areGrantsFetching = ref<boolean>(true);
const search = ref<string>('');
const searchTimer = ref<NodeJS.Timeout>();
const selected = ref([]);
const sortBy = [{ key: 'date', order: 'asc' }];
const headers = [
{
title: 'Name',
align: 'start',
key: 'name',
},
{ title: 'Type', key: 'type' },
{ title: 'Status', key: 'status' },
{ title: 'Permissions', key: 'permissions' },
{ title: 'Date Created', key: 'date' },
];
const accesses = [
{
name: 'Backup',
date: '02 Mar 2023',
type: 'Access Grant',
permissions: 'All',
status: 'Active',
},
{
name: 'S3 Test',
date: '03 Mar 2023',
type: 'S3 Credentials',
permissions: 'Read, Write',
status: 'Expired',
},
{
name: 'CLI Demo',
date: '04 Mar 2023',
type: 'CLI Access',
permissions: 'Read, Write, List',
status: 'Active',
},
{
name: 'Sharing',
date: '08 Mar 2023',
type: 'Access Grant',
permissions: 'Read, Delete',
status: 'Active',
},
{
name: 'Sync Int',
date: '12 Mar 2023',
type: 'S3 Credentials',
permissions: 'All',
status: 'Expired',
},
{ title: 'Date Created', key: 'createdAt' },
];
/**
* Returns access grants cursor from store.
*/
const cursor = computed((): AccessGrantCursor => {
return agStore.state.cursor;
});
/**
* Returns access grants page from store.
*/
const page = computed((): AccessGrantsPage => {
return agStore.state.page;
});
/**
* Fetches Access records depending on page and limit.
*/
async function fetch(page = FIRST_PAGE, limit = DEFAULT_PAGE_LIMIT): Promise<void> {
try {
await agStore.getAccessGrants(page, projectsStore.state.selectedProject.id, limit);
if (areGrantsFetching.value) areGrantsFetching.value = false;
} catch (error) {
notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
}
}
/**
* Handles update table rows limit event.
*/
function onUpdateLimit(limit: number): void {
fetch(page.value.currentPage, limit);
}
/**
* Handles update table page event.
*/
function onUpdatePage(page: number): void {
fetch(page, cursor.value.limit);
}
/**
* Handles update table sorting event.
*/
function onUpdateSortBy(sortBy: {key: keyof AccessGrantsOrderBy, order: keyof SortDirection}[]): void {
if (!sortBy.length) return;
const sorting = sortBy[0];
agStore.setSortingBy(AccessGrantsOrderBy[sorting.key]);
agStore.setSortingDirection(SortDirection[sorting.order]);
fetch(FIRST_PAGE, cursor.value.limit);
}
/**
* Handles update table search.
*/
watch(() => search.value, () => {
clearTimeout(searchTimer.value);
searchTimer.value = setTimeout(() => {
agStore.setSearchQuery(search.value);
fetch();
}, 500); // 500ms delay for every new call.
});
onMounted(() => {
fetch();
});
</script>