web/satellite/vuetify: add charts to project dashboard
Imported chart components from main project to vuetify app project dashboard with slight updates. Issue: https://github.com/storj/storj/issues/6071 Change-Id: I51254ea60aab59c7a841784b5dac7d41446e1df4
This commit is contained in:
parent
fcbb37fb66
commit
62f52c829a
@ -29,6 +29,7 @@ const props = withDefaults(defineProps<{
|
||||
before: Date,
|
||||
width: number,
|
||||
height: number,
|
||||
isVuetify?: boolean,
|
||||
}>(), {
|
||||
settledData: () => [],
|
||||
allocatedData: () => [],
|
||||
@ -36,6 +37,7 @@ const props = withDefaults(defineProps<{
|
||||
before: () => new Date(),
|
||||
width: 0,
|
||||
height: 0,
|
||||
isVuetify: false,
|
||||
});
|
||||
|
||||
const chartKey = ref<number>(0);
|
||||
@ -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);
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
@use './settings';
|
||||
@import 'static/styles/variables';
|
||||
|
||||
// Light Theme
|
||||
.v-theme--light {
|
||||
|
@ -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()" />
|
||||
@ -45,20 +78,25 @@
|
||||
</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();
|
||||
@ -66,6 +104,10 @@ 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.
|
||||
*/
|
||||
@ -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.
|
||||
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user