Skip to content

Commit

Permalink
web/satellite/vuetify: add charts to project dashboard
Browse files Browse the repository at this point in the history
Imported chart components from main project to vuetify app project dashboard with slight updates.

Issue:
#6071

Change-Id: I51254ea60aab59c7a841784b5dac7d41446e1df4
  • Loading branch information
VitaliiShpital authored and Storj Robot committed Jul 27, 2023
1 parent fcbb37f commit 62f52c8
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 6 deletions.
Expand Up @@ -29,13 +29,15 @@ const props = withDefaults(defineProps<{
before: Date,
width: number,
height: number,
isVuetify?: boolean,
}>(), {
settledData: () => [],
allocatedData: () => [],
since: () => new Date(),
before: () => new Date(),
width: 0,
height: 0,
isVuetify: false,
});
const chartKey = ref<number>(0);
Expand Down Expand Up @@ -99,10 +101,10 @@ function tooltip(tooltipModel: TooltipModel<ChartType>): void {
let tooltipParams: TooltipParams;
if (p.datasetIndex === 0) {
tooltipParams = new TooltipParams(tooltipModel, 'bandwidth-chart', 'settled-bandwidth-tooltip',
settledTooltipMarkUp(tooltipModel), -20, 78);
settledTooltipMarkUp(tooltipModel), -20, props.isVuetify ? 68 : 78);
} else {
tooltipParams = new TooltipParams(tooltipModel, 'bandwidth-chart', 'allocated-bandwidth-tooltip',
allocatedTooltipMarkUp(tooltipModel), 95, 78);
allocatedTooltipMarkUp(tooltipModel), 95, props.isVuetify ? 68 : 78);
}
Tooltip.custom(tooltipParams);
Expand Down
1 change: 1 addition & 0 deletions web/satellite/vuetify-poc/src/styles/styles.scss
Expand Up @@ -10,6 +10,7 @@
*/

@use './settings';
@import 'static/styles/variables';

// Light Theme
.v-theme--light {
Expand Down
124 changes: 120 additions & 4 deletions web/satellite/vuetify-poc/src/views/Dashboard.vue
Expand Up @@ -6,6 +6,39 @@
<PageTitleComponent title="Project Overview" />
<PageSubtitleComponent :subtitle="`Your ${limits.objectCount.toLocaleString()} files are stored in ${limits.segmentCount.toLocaleString()} segments around the world.`" />

<v-row class="d-flex align-center justify-center mt-2">
<v-col cols="12" md="6">
<v-card ref="chartContainer" title="Storage" variant="flat" :border="true" rounded="xlg">
<template v-if="!isDataFetching">
<h4 class="pl-4">{{ getDimension(storageUsage) }}</h4>
<StorageChart
:width="chartWidth"
:height="170"
:data="storageUsage"
:since="chartsSinceDate"
:before="chartsBeforeDate"
/>
</template>
</v-card>
</v-col>
<v-col cols="12" md="6">
<v-card title="Bandwidth" variant="flat" :border="true" rounded="xlg">
<template v-if="!isDataFetching">
<h4 class="pl-4">{{ getDimension([...settledBandwidthUsage, ...allocatedBandwidthUsage]) }}</h4>
<BandwidthChart
:width="chartWidth"
:height="170"
:settled-data="settledBandwidthUsage"
:allocated-data="allocatedBandwidthUsage"
:since="chartsSinceDate"
:before="chartsBeforeDate"
is-vuetify
/>
</template>
</v-card>
</v-col>
</v-row>

<v-row class="d-flex align-center justify-center mt-2">
<v-col cols="12" sm="6" md="4" lg="2">
<CardStatsComponent title="Files" subtitle="Project files" :data="limits.objectCount.toLocaleString()" />
Expand Down Expand Up @@ -45,27 +78,36 @@
</template>

<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { VContainer, VRow, VCol } from 'vuetify/components';
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { VContainer, VRow, VCol, VCard } from 'vuetify/components';
import { ComponentPublicInstance } from '@vue/runtime-core';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
import { useBillingStore } from '@/store/modules/billingStore';
import { useBucketsStore } from '@/store/modules/bucketsStore';
import { Project, ProjectLimits } from '@/types/projects';
import { DataStamp, Project, ProjectLimits } from '@/types/projects';
import { Dimensions, Size } from '@/utils/bytesSize';
import { ChartUtils } from '@/utils/chart';
import PageTitleComponent from '@poc/components/PageTitleComponent.vue';
import PageSubtitleComponent from '@poc/components/PageSubtitleComponent.vue';
import CardStatsComponent from '@poc/components/CardStatsComponent.vue';
import UsageProgressComponent from '@poc/components/UsageProgressComponent.vue';
import BandwidthChart from '@/components/project/dashboard/BandwidthChart.vue';
import StorageChart from '@/components/project/dashboard/StorageChart.vue';
const projectsStore = useProjectsStore();
const pmStore = useProjectMembersStore();
const agStore = useAccessGrantsStore();
const billingStore = useBillingStore();
const bucketsStore = useBucketsStore();
const isDataFetching = ref<boolean>(true);
const chartWidth = ref<number>(0);
const chartContainer = ref<ComponentPublicInstance>();
/**
* Returns current limits from store.
*/
Expand Down Expand Up @@ -101,6 +143,62 @@ const bucketsCount = computed((): number => {
return bucketsStore.state.page.totalCount;
});
/**
* Returns charts since date from store.
*/
const chartsSinceDate = computed((): Date => {
return projectsStore.state.chartDataSince;
});
/**
* Returns charts before date from store.
*/
const chartsBeforeDate = computed((): Date => {
return projectsStore.state.chartDataBefore;
});
/**
* Returns storage chart data from store.
*/
const storageUsage = computed((): DataStamp[] => {
return ChartUtils.populateEmptyUsage(
projectsStore.state.storageChartData, chartsSinceDate.value, chartsBeforeDate.value,
);
});
/**
* Returns settled bandwidth chart data from store.
*/
const settledBandwidthUsage = computed((): DataStamp[] => {
return ChartUtils.populateEmptyUsage(
projectsStore.state.settledBandwidthChartData, chartsSinceDate.value, chartsBeforeDate.value,
);
});
/**
* Returns allocated bandwidth chart data from store.
*/
const allocatedBandwidthUsage = computed((): DataStamp[] => {
return ChartUtils.populateEmptyUsage(
projectsStore.state.allocatedBandwidthChartData, chartsSinceDate.value, chartsBeforeDate.value,
);
});
/**
* Used container size recalculation for charts resizing.
*/
function recalculateChartWidth(): void {
chartWidth.value = chartContainer.value?.$el.getBoundingClientRect().width || 0;
}
/**
* Returns dimension for given data values.
*/
function getDimension(dataStamps: DataStamp[]): Dimensions {
const maxValue = Math.max(...dataStamps.map(s => s.value));
return new Size(maxValue).label;
}
/**
* Lifecycle hook after initial render.
* Fetches project limits.
Expand All @@ -109,14 +207,32 @@ onMounted(async (): Promise<void> => {
const projectID = selectedProject.value.id;
const FIRST_PAGE = 1;
window.addEventListener('resize', recalculateChartWidth);
recalculateChartWidth();
const now = new Date();
const past = new Date();
past.setDate(past.getDate() - 30);
try {
await Promise.all([
projectsStore.getDailyProjectData({ since: past, before: now }),
projectsStore.getProjectLimits(projectID),
billingStore.getProjectUsageAndChargesCurrentRollup(),
pmStore.getProjectMembers(FIRST_PAGE, projectID),
agStore.getAccessGrants(FIRST_PAGE, projectID),
bucketsStore.getBuckets(FIRST_PAGE, projectID),
]);
} catch (error) { /* empty */ }
} catch (error) { /* empty */ } finally {
isDataFetching.value = false;
}
});
/**
* Lifecycle hook before component destruction.
* Removes event listener on window resizing.
*/
onBeforeUnmount((): void => {
window.removeEventListener('resize', recalculateChartWidth);
});
</script>

0 comments on commit 62f52c8

Please sign in to comment.