Skip to content

Commit

Permalink
web/satellite/v2: allow user to download historical usage report
Browse files Browse the repository at this point in the history
Added the ability to download historical usage report for past month, past year or custom date range (not bigger than 13 month).

Issue:
#6513

Change-Id: I23a2a33489fa4d41020f27447ea582b945a6201d
  • Loading branch information
VitaliiShpital authored and Storj Robot committed Jan 11, 2024
1 parent f502f50 commit 2414386
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 30 deletions.
Expand Up @@ -2,7 +2,7 @@
// See LICENSE for copying information.

<template>
<v-card rounded="lg" variant="flat" :border="true" class="mb-4">
<v-card rounded="lg" variant="flat" border class="mb-4">
<v-expansion-panels>
<v-expansion-panel rounded="lg">
<v-expansion-panel-title>
Expand Down Expand Up @@ -86,7 +86,8 @@
</tr>
</tbody>
</v-table>
<v-btn class="mt-4" variant="outlined" color="default" size="small" @click="downloadReport">
<v-btn class="mt-4" variant="outlined" color="default" size="small" :prepend-icon="mdiCalendar">
<detailed-usage-report-dialog :project-i-d="projectId" />
Download Report
</v-btn>
</v-expansion-panel-text>
Expand All @@ -108,6 +109,7 @@ import {
VRow,
VTable,
} from 'vuetify/components';
import { mdiCalendar } from '@mdi/js';
import { CENTS_MB_TO_DOLLARS_GB_SHIFT, centsToDollars, decimalShift, formatPrice } from '@/utils/strings';
import { ProjectCharge, ProjectCharges, ProjectUsagePriceModel } from '@/types/payments';
Expand All @@ -116,9 +118,9 @@ import { Size } from '@/utils/bytesSize';
import { SHORT_MONTHS_NAMES } from '@/utils/constants/date';
import { useBillingStore } from '@/store/modules/billingStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { Download } from '@/utils/download';
import { useNotify } from '@/utils/hooks';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import DetailedUsageReportDialog from '@poc/components/dialogs/DetailedUsageReportDialog.vue';
/**
* HOURS_IN_MONTH constant shows amount of hours in 30-day month.
Expand Down Expand Up @@ -166,19 +168,6 @@ const projectCharges = computed((): ProjectCharges => {
return billingStore.state.projectCharges as ProjectCharges;
});
/**
* Handles download usage report click logic.
*/
function downloadReport(): void {
try {
const link = projectsStore.getUsageReportLink(props.projectId);
Download.fileByLink(link);
notify.success('Usage report download started successfully.');
} catch (error) {
notify.notifyError(error, AnalyticsErrorEventSource.BILLING_AREA);
}
}
/**
* Returns project usage price model from store.
*/
Expand Down
@@ -0,0 +1,194 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

<template>
<v-dialog
v-model="dialog"
activator="parent"
width="auto"
min-width="400px"
transition="fade-transition"
>
<v-card rounded="xlg">
<v-sheet>
<v-card-item class="pl-7 py-4">
<template #prepend>
<v-card-title class="font-weight-bold">
Get Detailed Usage Report
</v-card-title>
</template>

<template #append>
<v-btn
icon="$close"
variant="text"
size="small"
color="default"
@click="dialog = false"
/>
</template>
</v-card-item>
</v-sheet>

<v-divider />

<v-form class="pa-8">
<p class="text-subtitle-2 mb-2">Select date range to generate your report:</p>
<v-chip-group v-model="option" mandatory filter color="primary">
<v-chip :value="Options.Month">Past Month</v-chip>
<v-chip :value="Options.Year">Past Year</v-chip>
<v-chip :value="Options.Custom">Choose Dates</v-chip>
</v-chip-group>
<v-date-picker
v-if="option === Options.Custom"
v-model="customRange"
header="Choose Dates"
multiple
show-adjacent-months
border
elevation="0"
rounded="lg"
/>
</v-form>

<v-divider />

<v-card-actions class="pa-7">
<v-row>
<v-col>
<v-btn variant="outlined" color="default" block @click="dialog = false">Cancel</v-btn>
</v-col>
<v-col>
<v-btn color="primary" variant="flat" block @click="downloadReport">Download Report</v-btn>
</v-col>
</v-row>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import {
VDialog,
VBtn,
VRow,
VCol,
VSheet,
VCard,
VCardItem,
VCardTitle,
VCardActions,
VDivider,
VChipGroup,
VChip,
VForm,
VDatePicker,
} from 'vuetify/components';
import { Download } from '@/utils/download';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { useNotify } from '@/utils/hooks';
enum Options {
Month = 0,
Year,
Custom,
}
const projectsStore = useProjectsStore();
const notify = useNotify();
const props = withDefaults(defineProps<{
projectID: string
}>(), {
projectID: '',
});
const dialog = ref<boolean>(false);
const option = ref<Options>(Options.Month);
const since = ref<Date>();
const before = ref<Date>();
const customRange = ref<Date[]>([]);
/**
* Sets past month as active option.
*/
function setPastMonth(): void {
const now = new Date();
since.value = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 1, now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes()));
before.value = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes()));
option.value = Options.Month;
}
/**
* Sets past year as active option.
*/
function setPastYear(): void {
const now = new Date();
since.value = new Date(Date.UTC(now.getUTCFullYear() - 1, now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes()));
before.value = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes()));
option.value = Options.Year;
}
/**
* Sets custom date range as active option.
*/
function setChooseDates(): void {
since.value = undefined;
before.value = undefined;
option.value = Options.Custom;
}
function downloadReport(): void {
if (!(since.value && before.value)) {
notify.error('Please select date range', AnalyticsErrorEventSource.DETAILED_USAGE_REPORT_MODAL);
return;
}
try {
const link = projectsStore.getUsageReportLink(since.value, before.value, props.projectID);
Download.fileByLink(link);
notify.success('Usage report download started successfully.');
} catch (error) {
notify.notifyError(error, AnalyticsErrorEventSource.DETAILED_USAGE_REPORT_MODAL);
}
}
watch(customRange, () => {
if (customRange.value.length > 2) {
customRange.value = customRange.value.slice(0, 2);
return;
}
if (customRange.value.length < 2) {
since.value = undefined;
before.value = undefined;
return;
}
let [start, end] = customRange.value;
if (start.getTime() > end.getTime()) {
[start, end] = [end, start];
}
since.value = new Date(Date.UTC(start.getFullYear(), start.getMonth(), start.getDate(), start.getHours(), start.getMinutes()));
before.value = new Date(Date.UTC(end.getFullYear(), end.getMonth(), end.getDate(), end.getHours(), end.getMinutes()));
});
watch(option, () => {
switch (option.value) {
case Options.Month:
setPastMonth();
break;
case Options.Year:
setPastYear();
break;
case Options.Custom:
setChooseDates();
}
}, { immediate: true });
</script>
17 changes: 4 additions & 13 deletions web/satellite/vuetify-poc/src/views/Billing.vue
Expand Up @@ -155,7 +155,8 @@
<v-col>
<v-card title="Detailed Usage Report" subtitle="Get a complete usage report for all your projects." border variant="flat">
<v-card-text>
<v-btn variant="outlined" color="default" size="small" @click="downloadReport">
<v-btn variant="outlined" color="default" size="small" :prepend-icon="mdiCalendar">
<detailed-usage-report-dialog />
Download Report
</v-btn>
</v-card-text>
Expand Down Expand Up @@ -218,7 +219,7 @@ import {
VProgressCircular,
} from 'vuetify/components';
import { useRoute, useRouter } from 'vue-router';
import { mdiPlus } from '@mdi/js';
import { mdiCalendar, mdiPlus } from '@mdi/js';
import { useLoading } from '@/composables/useLoading';
import { useNotify } from '@/utils/hooks';
Expand All @@ -229,7 +230,6 @@ import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames
import { SHORT_MONTHS_NAMES } from '@/utils/constants/date';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { useConfigStore } from '@/store/modules/configStore';
import { Download } from '@/utils/download';
import { useLowTokenBalance } from '@/composables/useLowTokenBalance';
import { Project } from '@/types/projects';
import { RouteName } from '@poc/router';
Expand All @@ -243,6 +243,7 @@ import StorjTokenCardComponent from '@poc/components/StorjTokenCardComponent.vue
import TokenTransactionsTableComponent from '@poc/components/TokenTransactionsTableComponent.vue';
import ApplyCouponCodeDialog from '@poc/components/dialogs/ApplyCouponCodeDialog.vue';
import LowTokenBalanceBanner from '@poc/components/LowTokenBalanceBanner.vue';
import DetailedUsageReportDialog from '@poc/components/dialogs/DetailedUsageReportDialog.vue';
enum TABS {
overview,
Expand Down Expand Up @@ -357,16 +358,6 @@ const isCouponActive = computed((): boolean => {
return !!c && (c.duration === 'forever' || (!!c.expiresAt && now < c.expiresAt.getTime()));
});
function downloadReport(): void {
try {
const link = projectsStore.getUsageReportLink();
Download.fileByLink(link);
notify.success('Usage report download started successfully.');
} catch (error) {
notify.notifyError(error, AnalyticsErrorEventSource.BILLING_AREA);
}
}
function onAddTokensClicked(): void {
tab.value = TABS['payment-methods'];
tokenCardComponent.value?.onAddTokens();
Expand Down

0 comments on commit 2414386

Please sign in to comment.