aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/site/components/sidebar/Sidebar.vue1
-rw-r--r--src/site/components/statistics/byte.vue26
-rw-r--r--src/site/components/statistics/byteUsage.vue31
-rw-r--r--src/site/components/statistics/detailed.vue33
-rw-r--r--src/site/components/statistics/generic.vue26
-rw-r--r--src/site/components/statistics/time.vue46
-rw-r--r--src/site/pages/dashboard/admin/statistics.vue103
-rw-r--r--src/site/store/admin.js12
8 files changed, 277 insertions, 1 deletions
diff --git a/src/site/components/sidebar/Sidebar.vue b/src/site/components/sidebar/Sidebar.vue
index dc261ee..98c3c81 100644
--- a/src/site/components/sidebar/Sidebar.vue
+++ b/src/site/components/sidebar/Sidebar.vue
@@ -29,6 +29,7 @@
</template>
<b-menu-item icon="account" label="Users" tag="nuxt-link" to="/dashboard/admin/users" exact />
<b-menu-item icon="cog-outline" label="Settings" tag="nuxt-link" to="/dashboard/admin/settings" exact />
+ <!--<b-menu-item icon="chart-line" label="Statistics" tag="nuxt-link" to="/dashboard/admin/statistics" exact />-->
</b-menu-item>
<b-menu-item
class="item"
diff --git a/src/site/components/statistics/byte.vue b/src/site/components/statistics/byte.vue
new file mode 100644
index 0000000..05852cd
--- /dev/null
+++ b/src/site/components/statistics/byte.vue
@@ -0,0 +1,26 @@
+<template>
+ <div>
+ <div class="columns">
+ <div class="column is-2">
+ {{ title }}
+ </div>
+ <div class="column">
+ {{ (value / 1024 / 1024 / 1024).toFixed(2) }} GiB
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: {
+ title: {
+ 'type': String,
+ 'default': null
+ },
+ value: {
+ 'type': Number,
+ 'default': null
+ }
+ }
+};
+</script>
diff --git a/src/site/components/statistics/byteUsage.vue b/src/site/components/statistics/byteUsage.vue
new file mode 100644
index 0000000..740feff
--- /dev/null
+++ b/src/site/components/statistics/byteUsage.vue
@@ -0,0 +1,31 @@
+<template>
+ <div>
+ <div class="columns">
+ <div class="column is-2">
+ {{ title }}
+ </div>
+ <div class="column">
+ {{ (used / 1024 / 1024 / 1024).toFixed(2) }} GiB /
+ {{ (total / 1024 / 1024 / 1024).toFixed(2) }} GiB ({{ ((used * 100) / total).toFixed(2) }}%)
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: {
+ title: {
+ 'type': String,
+ 'default': null
+ },
+ used: {
+ 'type': Number,
+ 'default': null
+ },
+ total: {
+ 'type': Number,
+ 'default': null
+ }
+ }
+};
+</script>
diff --git a/src/site/components/statistics/detailed.vue b/src/site/components/statistics/detailed.vue
new file mode 100644
index 0000000..8a0722e
--- /dev/null
+++ b/src/site/components/statistics/detailed.vue
@@ -0,0 +1,33 @@
+<template>
+ <div>
+ <div class="columns">
+ <div class="column is-2">
+ {{ title }}
+ </div>
+ <div class="column">
+ <b-table :data="data || []" :mobile-cards="true">
+ <b-table-column v-slot="props" field="type" label="Type">
+ {{ props.row.key }}
+ </b-table-column>
+ <b-table-column v-slot="props" field="count" label="Count">
+ {{ props.row.value }}
+ </b-table-column>
+ </b-table>
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: {
+ title: {
+ 'type': String,
+ 'default': null
+ },
+ data: {
+ 'type': Array,
+ 'default': () => []
+ }
+ }
+};
+</script>
diff --git a/src/site/components/statistics/generic.vue b/src/site/components/statistics/generic.vue
new file mode 100644
index 0000000..704be7a
--- /dev/null
+++ b/src/site/components/statistics/generic.vue
@@ -0,0 +1,26 @@
+<template>
+ <div>
+ <div class="columns">
+ <div class="column is-2">
+ {{ title }}
+ </div>
+ <div class="column">
+ {{ value }}
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: {
+ title: {
+ 'type': String,
+ 'default': null
+ },
+ value: {
+ 'type': [Number, String],
+ 'default': null
+ }
+ }
+};
+</script>
diff --git a/src/site/components/statistics/time.vue b/src/site/components/statistics/time.vue
new file mode 100644
index 0000000..ff1bb8d
--- /dev/null
+++ b/src/site/components/statistics/time.vue
@@ -0,0 +1,46 @@
+<template>
+ <div>
+ <div class="columns">
+ <div class="column is-2">
+ {{ title }}
+ </div>
+ <div class="column">
+ {{ parsedTime }}
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: {
+ title: {
+ 'type': String,
+ 'default': null
+ },
+ value: {
+ 'type': Number,
+ 'default': null
+ }
+ },
+ computed: {
+ parsedTime() {
+ let seconds = this.value;
+ const days = Math.floor(seconds / 86400);
+ seconds %= 86400;
+ let hours = Math.floor(seconds / 3600);
+ seconds %= 3600;
+ let minutes = Math.floor(seconds / 60);
+ seconds %= 60;
+
+ if (hours < 10) hours = `0${hours}`;
+ if (minutes < 10) minutes = `0${minutes}`;
+ if (seconds < 10) seconds = `0${seconds}`;
+
+ if (days > 0) {
+ return `${days}d ${hours}:${minutes}:${seconds}`;
+ }
+ return `${hours}:${minutes}:${seconds}`;
+ }
+ }
+};
+</script>
diff --git a/src/site/pages/dashboard/admin/statistics.vue b/src/site/pages/dashboard/admin/statistics.vue
new file mode 100644
index 0000000..3a2891c
--- /dev/null
+++ b/src/site/pages/dashboard/admin/statistics.vue
@@ -0,0 +1,103 @@
+<template>
+ <section class="section is-fullheight dashboard">
+ <div class="container">
+ <div class="columns">
+ <div class="column is-narrow">
+ <Sidebar />
+ </div>
+ <div class="column">
+ <h2 class="subtitle">
+ Statistics
+ </h2>
+ <hr>
+ <template v-for="category in Object.keys(stats)">
+ <div :key="category"
+ class="stats-container">
+ <h2 class="title">
+ {{ category }}
+ </h2>
+ <template v-for="item in Object.keys(stats[category])">
+ <!-- If it's plain text or a number, just print it -->
+ <template v-if="typeof stats[category][item] === 'string' || typeof stats[category][item] === 'number'">
+ <generic :key="item"
+ :title="item"
+ :value="stats[category][item]" />
+ </template>
+
+ <!-- If it's an object then we need to do some magic -->
+ <template v-else-if="typeof stats[category][item] === 'object'">
+ <byteUsage v-if="stats[category][item].type === 'byteUsage'"
+ :key="item"
+ :title="item"
+ :used="stats[category][item].value.used"
+ :total="stats[category][item].value.total" />
+ <byte v-else-if="stats[category][item].type === 'byte'"
+ :key="item"
+ :title="item"
+ :value="stats[category][item].value" />
+ <beat v-else-if="stats[category][item].type === 'time'"
+ :key="item"
+ :title="item"
+ :value="stats[category][item].value" />
+ <detailed v-else-if="stats[category][item].type === 'detailed'"
+ :key="item"
+ :title="item"
+ :data="stats[category][item].data" />
+ </template>
+ </template>
+ </div>
+ </template>
+ </div>
+ </div>
+ </div>
+ </section>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+import Sidebar from '~/components/sidebar/Sidebar.vue';
+import byteUsage from '~/components/statistics/byteUsage.vue';
+import byte from '~/components/statistics/byte.vue';
+import beat from '~/components/statistics/time.vue';
+import detailed from '~/components/statistics/detailed.vue';
+import generic from '~/components/statistics/generic.vue';
+
+export default {
+ components: {
+ Sidebar,
+ byteUsage,
+ byte,
+ beat,
+ detailed,
+ generic
+ },
+ middleware: ['auth', 'admin', ({ store }) => {
+ try {
+ store.dispatch('admin/fetchStatistics');
+ } catch (e) {
+ console.error(e);
+ }
+ }],
+ computed: mapState({
+ stats: state => state.admin.statistics
+ }),
+ methods: {},
+ head() {
+ return {
+ title: 'Service statistics'
+ };
+ }
+};
+</script>
+<style lang="scss" scoped>
+@import '~/assets/styles/_colors.scss';
+h2.title {
+ color: $defaultTextColor;
+}
+div.stats-container {
+ padding: 1rem;
+ background: #1c1e23;
+ box-shadow: rgba(15, 17, 21, 0.35) 0px 6px 9px 0px;
+ margin-bottom: 1rem;
+}
+</style>
diff --git a/src/site/store/admin.js b/src/site/store/admin.js
index 58b63b5..b2d1926 100644
--- a/src/site/store/admin.js
+++ b/src/site/store/admin.js
@@ -11,7 +11,8 @@ export const state = () => ({
files: []
},
file: {},
- settings: {}
+ settings: {},
+ statistics: {}
});
export const actions = {
@@ -21,6 +22,12 @@ export const actions = {
return response;
},
+ async fetchStatistics({ commit }) {
+ const response = await this.$axios.$get('service/statistics');
+ commit('setStatistics', response);
+
+ return response;
+ },
async fetchUsers({ commit }) {
const response = await this.$axios.$get('admin/users');
commit('setUsers', response);
@@ -89,6 +96,9 @@ export const mutations = {
setSettings(state, { config }) {
state.settings = config;
},
+ setStatistics(state, { statistics }) {
+ state.statistics = statistics;
+ },
setUsers(state, { users }) {
state.users = users;
},