aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZephyrrus <[email protected]>2021-01-07 23:55:37 +0200
committerZephyrrus <[email protected]>2021-01-07 23:55:37 +0200
commit925080f6a08a1f1515143db1bd6aef8109f5fb67 (patch)
tree298476e0f2aea59422bcc46fb1e1ce8bb4f19c18
parentchore: revert nuxt update, it breaks SSR in development mode, not worth it. (diff)
downloadhost.fuwn.me-925080f6a08a1f1515143db1bd6aef8109f5fb67.tar.xz
host.fuwn.me-925080f6a08a1f1515143db1bd6aef8109f5fb67.zip
chore: refactor stats generator to use an enum for types
fix: saved data not being converted to JSON automatically when using SQLite (and possibly MSSQL) feat: display when a stat was generated in the section's header fix: not being able to click through the footer (sorry IE11 users, you still won't be able to click through it) fix: add is-mobile to columns so they don't stack on top of each other feat: add text next to the NSFW toggle and make it look like the elements around it (begone round iOS edges)
-rw-r--r--src/api/routes/service/statsGET.js24
-rw-r--r--src/api/utils/StatsGenerator.js34
-rw-r--r--src/api/utils/Util.js13
-rw-r--r--src/site/components/album/AlbumDetails.vue8
-rw-r--r--src/site/components/footer/Footer.vue6
-rw-r--r--src/site/components/sidebar/Sidebar.vue2
-rw-r--r--src/site/components/statistics/byte.vue2
-rw-r--r--src/site/components/statistics/byteUsage.vue2
-rw-r--r--src/site/components/statistics/detailed.vue17
-rw-r--r--src/site/components/statistics/generic.vue2
-rw-r--r--src/site/components/statistics/time.vue2
-rw-r--r--src/site/pages/dashboard/admin/statistics.vue7
-rw-r--r--src/site/pages/dashboard/albums/index.vue2
13 files changed, 93 insertions, 28 deletions
diff --git a/src/api/routes/service/statsGET.js b/src/api/routes/service/statsGET.js
index d6fa69e..2241ca8 100644
--- a/src/api/routes/service/statsGET.js
+++ b/src/api/routes/service/statsGET.js
@@ -1,5 +1,6 @@
const Route = require('../../structures/Route');
const StatsGenerator = require('../../utils/StatsGenerator');
+const moment = require('moment');
// Thank you Bobby for the stats code https://github.com/BobbyWibowo/lolisafe/blob/safe.fiery.me/controllers/utilsController.js
class filesGET extends Route {
@@ -9,12 +10,23 @@ class filesGET extends Route {
async run(req, res, db) {
const cachedStats = await db('statistics')
- .select('type', 'data', 'batchId')
+ .select('type', 'data', 'batchId', 'createdAt')
.where('batchId', '=', db('statistics').max('batchId'));
- let stats = cachedStats.reduce((acc, { type, data }) => {
+ let stats = cachedStats.reduce((acc, { type, data, createdAt }) => {
try {
- acc[type] = JSON.parse(data);
+ // pg returns json, sqlite retuns a string...
+ if (typeof data === 'string' || data instanceof String) {
+ acc[type] = JSON.parse(data);
+ } else {
+ acc[type] = data;
+ }
+
+ acc[type].meta = {
+ cached: true,
+ generatedOn: moment(createdAt).format('MMMM Do YYYY, h:mm:ss a z'), // pg returns this as a date, sqlite3 returns an unix timestamp :<
+ type: StatsGenerator.Type.HIDDEN
+ };
} catch (e) {
console.error(e);
}
@@ -24,10 +36,12 @@ class filesGET extends Route {
stats = { ...stats, ...(await StatsGenerator.getMissingStats(db, Object.keys(stats))) };
- return res.json(StatsGenerator.keyOrder.reduce((acc, k) => {
+ const ordered = StatsGenerator.keyOrder.reduce((acc, k) => {
acc[k] = stats[k];
return acc;
- }, {}));
+ }, {});
+
+ return res.json({ statistics: ordered });
}
}
diff --git a/src/api/utils/StatsGenerator.js b/src/api/utils/StatsGenerator.js
index 2e48f32..ce73cd2 100644
--- a/src/api/utils/StatsGenerator.js
+++ b/src/api/utils/StatsGenerator.js
@@ -1,6 +1,22 @@
const si = require('systeminformation');
class StatsGenerator {
+ // symbols would be better because they're unique, but harder to serialize them
+ static Type = Object.freeze({
+ // should contain key value: number
+ TIME: 'time',
+ // should contain key value: number
+ BYTE: 'byte',
+ // should contain key value: { used: number, total: number }
+ BYTE_USAGE: 'byteUsage',
+ // should contain key data: Array<{ key: string, value: number | string }>
+ // and optionally a count/total
+ DETAILED: 'detailed',
+ // hidden type should be skipped during iteration, can contain anything
+ // these should be treated on a case by case basis on the frontend
+ HIDDEN: 'hidden'
+ });
+
static statGenerators = {
system: StatsGenerator.getSystemInfo,
fileSystems: StatsGenerator.getFileSystemsInfo,
@@ -30,20 +46,20 @@ class StatsGenerator {
used: mem.active,
total: mem.total
},
- type: 'byteUsage'
+ type: StatsGenerator.Type.BYTE_USAGE
},
'Memory Usage': {
value: process.memoryUsage().rss,
- type: 'byte'
+ type: StatsGenerator.Type.BYTE
},
'System Uptime': {
value: time.uptime,
- type: 'time'
+ type: StatsGenerator.Type.TIME
},
'Node.js': `${process.versions.node}`,
'Service Uptime': {
value: Math.floor(nodeUptime),
- type: 'time'
+ type: StatsGenerator.Type.TIME
}
};
}
@@ -58,7 +74,7 @@ class StatsGenerator {
total: fs.size,
used: fs.used
},
- type: 'byteUsage'
+ type: StatsGenerator.Type.BYTE_USAGE
};
}
@@ -73,11 +89,11 @@ class StatsGenerator {
'Others': {
data: {},
count: 0,
- type: 'detailed'
+ type: StatsGenerator.Type.DETAILED
},
'Size in DB': {
value: 0,
- type: 'byte'
+ type: StatsGenerator.Type.BYTE
}
};
@@ -88,7 +104,7 @@ class StatsGenerator {
'Total': uploads.length,
'Size in DB': {
value: uploads.reduce((acc, upload) => acc + parseInt(upload.size, 10), 0),
- type: 'byte'
+ type: StatsGenerator.Type.BYTE
}
};
};
@@ -127,7 +143,7 @@ class StatsGenerator {
Others: {
data,
count,
- type: 'detailed'
+ type: StatsGenerator.Type.DETAILED
}
};
};
diff --git a/src/api/utils/Util.js b/src/api/utils/Util.js
index 658ac61..6feedd4 100644
--- a/src/api/utils/Util.js
+++ b/src/api/utils/Util.js
@@ -311,11 +311,18 @@ class Util {
return extname + multi;
}
- static async saveStatsToDb() {
+ // TODO: Allow choosing what to save to db and what stats we care about in general
+ // TODO: if a stat is not saved to db but selected to be shows on the dashboard, it will be generated during the request
+ static async saveStatsToDb(force) {
+ // If there were no changes since the instance started, don't generate new stats
+ // OR
// if we alredy saved a stats to the db, and there were no new changes to the db since then
// skip generating and saving new stats.
- // XXX: Should we save non-db related statistics to the database anyway? (like performance, disk usage)
- if (statsLastSavedTime && statsLastSavedTime > db.userParams.lastMutationTime) {
+ if (!force &&
+ (!db.userParams.lastMutationTime ||
+ (statsLastSavedTime && statsLastSavedTime > db.userParams.lastMutationTime)
+ )
+ ) {
return;
}
diff --git a/src/site/components/album/AlbumDetails.vue b/src/site/components/album/AlbumDetails.vue
index 81819b2..da472b0 100644
--- a/src/site/components/album/AlbumDetails.vue
+++ b/src/site/components/album/AlbumDetails.vue
@@ -101,7 +101,13 @@
<div class="level-item">
<b-switch
:value="nsfw"
- @input="toggleNsfw()" />
+ :rounded="false"
+ type="is-warning"
+ class="has-text-light"
+ left-label
+ @input="toggleNsfw()">
+ NSFW
+ </b-switch>
</div>
<div class="level-item">
<button
diff --git a/src/site/components/footer/Footer.vue b/src/site/components/footer/Footer.vue
index 96774e7..0c77603 100644
--- a/src/site/components/footer/Footer.vue
+++ b/src/site/components/footer/Footer.vue
@@ -72,6 +72,9 @@ export default {
<style lang="scss" scoped>
@import '~/assets/styles/_colors.scss';
footer {
+ pointer-events: none;
+ touch-action: none;
+
@media screen and (min-width: 1025px) {
position: fixed;
bottom: 0;
@@ -84,6 +87,9 @@ export default {
.container {
.column {
+ pointer-events: auto;
+ touch-action: auto;
+
text-align: center;
@media screen and (min-width: 1025px) {
margin-right: 2rem;
diff --git a/src/site/components/sidebar/Sidebar.vue b/src/site/components/sidebar/Sidebar.vue
index 98c3c81..a021226 100644
--- a/src/site/components/sidebar/Sidebar.vue
+++ b/src/site/components/sidebar/Sidebar.vue
@@ -29,7 +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 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
index 05852cd..16f4427 100644
--- a/src/site/components/statistics/byte.vue
+++ b/src/site/components/statistics/byte.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <div class="columns">
+ <div class="columns is-mobile">
<div class="column is-2">
{{ title }}
</div>
diff --git a/src/site/components/statistics/byteUsage.vue b/src/site/components/statistics/byteUsage.vue
index 740feff..9062e5e 100644
--- a/src/site/components/statistics/byteUsage.vue
+++ b/src/site/components/statistics/byteUsage.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <div class="columns">
+ <div class="columns is-mobile">
<div class="column is-2">
{{ title }}
</div>
diff --git a/src/site/components/statistics/detailed.vue b/src/site/components/statistics/detailed.vue
index 8a0722e..0d93e9a 100644
--- a/src/site/components/statistics/detailed.vue
+++ b/src/site/components/statistics/detailed.vue
@@ -1,11 +1,11 @@
<template>
<div>
- <div class="columns">
+ <div class="columns is-mobile">
<div class="column is-2">
{{ title }}
</div>
<div class="column">
- <b-table :data="data || []" :mobile-cards="true">
+ <b-table v-if="data.length" :data="data || []" :mobile-cards="true" narrowed class="details">
<b-table-column v-slot="props" field="type" label="Type">
{{ props.row.key }}
</b-table-column>
@@ -13,6 +13,9 @@
{{ props.row.value }}
</b-table-column>
</b-table>
+ <template v-else>
+ -
+ </template>
</div>
</div>
</div>
@@ -31,3 +34,13 @@ export default {
}
};
</script>
+<style lang="scss" scoped>
+ .details ::v-deep .table-wrapper {
+ box-shadow: none;
+
+ .table {
+ border-radius: unset;
+ background: #2A2E3C;
+ }
+ }
+</style>
diff --git a/src/site/components/statistics/generic.vue b/src/site/components/statistics/generic.vue
index 704be7a..aa0f7e9 100644
--- a/src/site/components/statistics/generic.vue
+++ b/src/site/components/statistics/generic.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <div class="columns">
+ <div class="columns is-mobile">
<div class="column is-2">
{{ title }}
</div>
diff --git a/src/site/components/statistics/time.vue b/src/site/components/statistics/time.vue
index ff1bb8d..54174da 100644
--- a/src/site/components/statistics/time.vue
+++ b/src/site/components/statistics/time.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <div class="columns">
+ <div class="columns is-mobile">
<div class="column is-2">
{{ title }}
</div>
diff --git a/src/site/pages/dashboard/admin/statistics.vue b/src/site/pages/dashboard/admin/statistics.vue
index 4d601cf..ecee102 100644
--- a/src/site/pages/dashboard/admin/statistics.vue
+++ b/src/site/pages/dashboard/admin/statistics.vue
@@ -14,8 +14,11 @@
<div :key="category"
class="stats-container">
<h2 class="title">
- {{ category }}
+ {{ category }} <span v-if="stats[category].meta" class="is-size-7 is-pulled-right is-family-monospace has-text-grey-light">
+ generated on {{ stats[category].meta.generatedOn }}
+ </span>
</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'">
@@ -25,7 +28,7 @@
</template>
<!-- If it's an object then we need to do some magic -->
- <template v-else-if="typeof stats[category][item] === 'object'">
+ <template v-else-if="typeof stats[category][item] === 'object' && stats[category][item].type !== 'hidden'">
<byteUsage v-if="stats[category][item].type === 'byteUsage'"
:key="item"
:title="item"
diff --git a/src/site/pages/dashboard/albums/index.vue b/src/site/pages/dashboard/albums/index.vue
index e3ccc08..2ebfb3f 100644
--- a/src/site/pages/dashboard/albums/index.vue
+++ b/src/site/pages/dashboard/albums/index.vue
@@ -105,7 +105,7 @@ export default {
div.search-container {
padding: 1rem 2rem;
- background-color: $base-2;
+ // background-color: $base-2;
}
div.column > h2.subtitle { padding-top: 1px; }