Skip to content

Commit

Permalink
Merge pull request #91 from offspot/package_popularity_details
Browse files Browse the repository at this point in the history
  • Loading branch information
benoit74 authored Jan 22, 2024
2 parents dd91d99 + 8c13ac5 commit 9733aed
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 44 deletions.
4 changes: 3 additions & 1 deletion frontend/src/components/DashboardPackagePopularity.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const packagePopularityStore = usePackagePopularityStore()
v-for="item in packagePopularityStore.firstItems"
:key="item.package"
>
<v-list-item-title class="font-weight-medium text-body-2 mx-4 my-5">
<v-list-item-title
class="font-weight-medium text-body-2 mx-4 mt-6 mb-7"
>
{{ item.package }}
</v-list-item-title>

Expand Down
119 changes: 119 additions & 0 deletions frontend/src/components/PackagePopularityElement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<script setup lang="ts">
import { usePackagePopularityStore } from '../stores/packagePopularity'
const packagePopularityStore = usePackagePopularityStore()
import { computed } from 'vue'
import VueApexCharts from 'vue3-apexcharts'
const props = withDefaults(
defineProps<{
package: string
visits: number
total: number
inverted: boolean
}>(),
{ inverted: false },
)
const percentage = computed(() => {
const value = (100.0 * props.visits) / props.total
if (value < 10) {
return value.toFixed(1)
} else {
return value.toFixed(0)
}
})
const chartOptions = computed(() => {
return {
chart: { type: 'radialBar', height: '180px' },
plotOptions: {
radialBar: {
track: {
opacity: 0.1,
background: '#020202',
strokeWidth: '50%',
},
dataLabels: {
name: {
show: false,
},
value: {
offsetY: 10,
fontSize: '1.8em',
fontWeight: '600',
formatter: () => `${percentage.value} %`,
},
},
},
},
fill: {
type: 'solid',
opacity: 1,
colors: [
props.inverted
? '#000000'
: packagePopularityStore.packageColor(props.package),
],
},
stroke: {
lineCap: 'round',
},
}
})
const cardStyle = computed(() =>
props.inverted
? {
'background-color': packagePopularityStore.packageColor(props.package),
}
: {},
)
</script>

<template>
<v-card :style="cardStyle">
<div class="d-flex">
<div class="chart-container">
<VueApexCharts
:options="chartOptions"
:series="[percentage]"
height="180px"
/>
</div>
<div class="ml-4 mt-4">
<div class="package-name">{{ props.package }}</div>
<div class="nb-visits">
<span>{{ props.visits }}</span> sessions
</div>
</div>
</div>
</v-card>
</template>

<style scoped>
.nb-visits {
position: absolute;
bottom: 30px;
font-size: 0.9em;
}
.nb-visits span {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 6px;
border-width: 4px;
border-color: rgba(0, 0, 0, 0);
border-style: solid;
padding: 2px 4px;
}
.package-name {
font-size: 1.2em;
font-weight: bold;
}
.chart-container {
position: relative;
top: -10px;
height: 130px;
width: 130px;
}
</style>
6 changes: 3 additions & 3 deletions frontend/src/stores/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ export const useMainStore = defineStore('main', {
date_part_2(): string {
switch (this.aggregationKind) {
case 'D':
return this.aggregationValue.split('-')[2] + ' '
return `${this.aggregationValue.split('-')[2]} `
case 'W':
if (this.aggregationValue.indexOf(' ') < 0) {
return '' // Race condition where space is not yet available
}
return this.aggregationValue.split(' ')[1].substring(1) + ' '
return `${this.aggregationValue.split(' ')[1].substring(1)} `
case 'M':
return monthText(this.aggregationValue.split('-')[1]) + ' '
return `${monthText(this.aggregationValue.split('-')[1])} `
case 'Y':
return this.aggregationValue
default:
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/stores/packagePopularity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const usePackagePopularityStore = defineStore('packagePopularity', {
return this.kpiValue.items
},
firstItems(): PackagePopularityKpiItem[] {
return this.kpiValue.items.slice(0, 6)
return this.kpiValue.items.slice(0, 5)
},
itemPercentage(): (item: PackagePopularityKpiItem) => number {
return (item: PackagePopularityKpiItem) =>
Expand All @@ -24,18 +24,21 @@ export const usePackagePopularityStore = defineStore('packagePopularity', {
return (item: PackagePopularityKpiItem) => {
const value = this.itemPercentage(item)
if (value < 10) {
return value.toFixed(1) + '%'
return `${value.toFixed(1)}%`
} else {
return value.toFixed(0) + '%'
return `${value.toFixed(0)}%`
}
}
},
itemLabel(): (item: PackagePopularityKpiItem) => string {
return (item: PackagePopularityKpiItem) => '' + item.visits
return (item: PackagePopularityKpiItem) => `${item.visits}`
},
itemColor(): (item: PackagePopularityKpiItem) => string {
return (item: PackagePopularityKpiItem) =>
useMainStore().getPackageColor(item.package)
return (item: PackagePopularityKpiItem) => this.packageColor(item.package)
},
packageColor(): (packageName: string) => string {
return (packageName: string) =>
useMainStore().getPackageColor(packageName)
},
},
})
4 changes: 2 additions & 2 deletions frontend/src/stores/totalUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const useTotalUsageStore = defineStore('totalUsage', {
return (item: TotalUsageKpiItem) => {
const value = item.minutesActivity / 60
if (value < 10) {
return value.toFixed(1) + 'h'
return `${value.toFixed(1)}h`
} else {
return value.toFixed(0) + 'h'
return `${value.toFixed(0)}h`
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/stores/uptime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export const useUptimeStore = defineStore('uptime', {
legend(): string {
const hours = this.kpiValue.nbMinutesOn / 60
if (hours < 10) {
return (this.kpiValue.nbMinutesOn / 60).toFixed(1) + 'h'
return `${(this.kpiValue.nbMinutesOn / 60).toFixed(1)}h`
} else {
return (this.kpiValue.nbMinutesOn / 60).toFixed(0) + 'h'
return `${(this.kpiValue.nbMinutesOn / 60).toFixed(0)}h`
}
},
},
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/types/ViewInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Information about a given view which is accessible from home page drawer
*/
export default interface ViewInfo {
title: string
icon: string
value: number
}
32 changes: 12 additions & 20 deletions frontend/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,20 @@
*/
export const getRandomColor = (): string => {
/*
Color scheme is from https://sashamaps.net/docs/resources/20-colors/
We selected colors which are differentiable for 99% of the population and just didn't used
the white which was hard to see in our design.
Color scheme is from https://venngage.com/tools/accessible-color-palette-generator#colorGenerator
We selected colors mostly randomly
*/
const colorScheme = [
'#e6194B',
'#3cb44b',
'#ffe119',
'#4363d8',
'#f58231',
'#42d4f4',
'#f032e6',
'#fabed4',
'#469990',
'#dcbeff',
'#9A6324',
'#fffac8',
'#800000',
'#aaffc3',
'#000075',
'#a9a9a9',
'#000000',
'#00bf7d',
'#00b4c5',
'#f57600',
'#8babf1',
'#e6308a',
'#89ce00',
'#e6308a',
'#9b8bf4',
'#606ff3',
'#9b8bf4',
]
return colorScheme[Math.floor(Math.random() * colorScheme.length)]
}
10 changes: 9 additions & 1 deletion frontend/src/views/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import DashboardPackagePopularity from '../components/DashboardPackagePopularity
import DashboardTotalUsage from '../components/DashboardTotalUsage.vue'
import DashboardSharedFiles from '../components/DashboardSharedFiles.vue'
import DashboardUptime from '../components/DashboardUptime.vue'
import { useMainStore, Page } from '../stores/main'
const mainStore = useMainStore()
</script>

<template>
Expand Down Expand Up @@ -34,7 +38,11 @@ import DashboardUptime from '../components/DashboardUptime.vue'
<v-container class="pa-0">
<v-row>
<v-col cols="12" lg="6">
<v-card elevation="0" class="package-popularity">
<v-card
elevation="0"
class="package-popularity"
@click="mainStore.currentPage = Page.PackagePopularity"
>
<DashboardPackagePopularity />
</v-card>
</v-col>
Expand Down
30 changes: 24 additions & 6 deletions frontend/src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import TotalUsage from '../views/TotalUsage.vue'
import { onMounted, computed } from 'vue'
import { useMainStore, Page } from '../stores/main'
import { useDisplay } from 'vuetify'
import ViewInfo from '@/types/ViewInfo'
const { mdAndUp, lgAndUp } = useDisplay()
const store = useMainStore()
Expand All @@ -20,6 +21,19 @@ onMounted(() => {
})
const height = computed(() => (mdAndUp.value ? 100 : 60))
const views: ViewInfo[] = [
{
title: 'Dashboard',
value: Page.Dashboard,
icon: 'far fa-envelope-open',
},
{
title: 'Package popularity',
value: Page.PackagePopularity,
icon: 'fas fa-chart-column',
},
]
</script>

<template>
Expand All @@ -38,9 +52,11 @@ const height = computed(() => (mdAndUp.value ? 100 : 60))
</div>
<div class="my-6"></div>
<DrawerItem
title="Dashboard"
:value="Page.Dashboard"
icon="far fa-envelope-open"
v-for="view in views"
:key="view.value"
:title="view.title"
:value="view.value"
:icon="view.icon"
active-class="active-big"
/>
</v-navigation-drawer>
Expand All @@ -58,10 +74,12 @@ const height = computed(() => (mdAndUp.value ? 100 : 60))
@click="store.toggleDrawerVisibility()"
></v-icon>
<DrawerItem
v-for="view in views"
:key="view.value"
class="py-6"
title="Dashboard"
:value="Page.Dashboard"
icon="far fa-envelope-open"
:title="view.title"
:value="view.value"
:icon="view.icon"
active-class="active-small"
/>
</v-navigation-drawer>
Expand Down
Loading

0 comments on commit 9733aed

Please sign in to comment.