summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-08-23 16:36:23 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-08-23 16:36:23 +0900
commit71a5662195b4b6a8d4d2c2fc357752b9da350b6f (patch)
tree1b6c4778bc1661bb32ba99a759b5300cb9c52f0d /src
parent1時間単位での集計を追加 (diff)
downloadsharkey-71a5662195b4b6a8d4d2c2fc357752b9da350b6f.tar.gz
sharkey-71a5662195b4b6a8d4d2c2fc357752b9da350b6f.tar.bz2
sharkey-71a5662195b4b6a8d4d2c2fc357752b9da350b6f.zip
一時間ごとのグラフも見れるように
Diffstat (limited to 'src')
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.drive-chart.chart.vue57
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.notes-chart.chart.vue101
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.users-chart.chart.vue57
-rw-r--r--src/server/api/endpoints/admin/chart.ts182
4 files changed, 250 insertions, 147 deletions
diff --git a/src/client/app/desktop/views/pages/admin/admin.drive-chart.chart.vue b/src/client/app/desktop/views/pages/admin/admin.drive-chart.chart.vue
index 3c537d8d6d..97f05571c3 100644
--- a/src/client/app/desktop/views/pages/admin/admin.drive-chart.chart.vue
+++ b/src/client/app/desktop/views/pages/admin/admin.drive-chart.chart.vue
@@ -1,11 +1,14 @@
<template>
-<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
- <polyline
- :points="points"
- fill="none"
- stroke-width="1"
- stroke="#555"/>
-</svg>
+<div>
+ <a @click="span = 'day'">Per day</a> | <a @click="span = 'hour'">Per hour</a>
+ <svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
+ <polyline
+ :points="points"
+ fill="none"
+ stroke-width="0.3"
+ stroke="#555"/>
+ </svg>
+</div>
</template>
<script lang="ts">
@@ -23,20 +26,40 @@ export default Vue.extend({
},
data() {
return {
- viewBoxX: 365,
- viewBoxY: 70,
- points: null
+ viewBoxX: 100,
+ viewBoxY: 30,
+ points: null,
+ span: 'day'
};
},
- created() {
- const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.drive.local.totalSize : d.drive.remote.totalSize));
+ computed: {
+ stats(): any[] {
+ return (
+ this.span == 'day' ? this.chart.perDay :
+ this.span == 'hour' ? this.chart.perHour :
+ null
+ );
+ }
+ },
+ watch: {
+ stats() {
+ this.render();
+ }
+ },
+ mounted() {
+ this.render();
+ },
+ methods: {
+ render() {
+ const peak = Math.max.apply(null, this.stats.map(d => this.type == 'local' ? d.drive.local.totalSize : d.drive.remote.totalSize));
- if (peak != 0) {
- const data = this.chart.slice().reverse().map(x => ({
- size: this.type == 'local' ? x.drive.local.totalSize : x.drive.remote.totalSize
- }));
+ if (peak != 0) {
+ const data = this.stats.slice().reverse().map(x => ({
+ size: this.type == 'local' ? x.drive.local.totalSize : x.drive.remote.totalSize
+ }));
- this.points = data.map((d, i) => `${i},${(1 - (d.size / peak)) * this.viewBoxY}`).join(' ');
+ this.points = data.map((d, i) => `${(this.viewBoxX / data.length) * i},${(1 - (d.size / peak)) * this.viewBoxY}`).join(' ');
+ }
}
}
});
diff --git a/src/client/app/desktop/views/pages/admin/admin.notes-chart.chart.vue b/src/client/app/desktop/views/pages/admin/admin.notes-chart.chart.vue
index 83c61c1313..fabb3f1bd1 100644
--- a/src/client/app/desktop/views/pages/admin/admin.notes-chart.chart.vue
+++ b/src/client/app/desktop/views/pages/admin/admin.notes-chart.chart.vue
@@ -1,27 +1,30 @@
<template>
-<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
- <polyline
- :points="pointsNote"
- fill="none"
- stroke-width="1"
- stroke="#41ddde"/>
- <polyline
- :points="pointsReply"
- fill="none"
- stroke-width="1"
- stroke="#f7796c"/>
- <polyline
- :points="pointsRenote"
- fill="none"
- stroke-width="1"
- stroke="#a1de41"/>
- <polyline
- :points="pointsTotal"
- fill="none"
- stroke-width="1"
- stroke="#555"
- stroke-dasharray="2 2"/>
-</svg>
+<div>
+ <a @click="span = 'day'">Per day</a> | <a @click="span = 'hour'">Per hour</a>
+ <svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
+ <polyline
+ :points="pointsNote"
+ fill="none"
+ stroke-width="0.3"
+ stroke="#41ddde"/>
+ <polyline
+ :points="pointsReply"
+ fill="none"
+ stroke-width="0.3"
+ stroke="#f7796c"/>
+ <polyline
+ :points="pointsRenote"
+ fill="none"
+ stroke-width="0.3"
+ stroke="#a1de41"/>
+ <polyline
+ :points="pointsTotal"
+ fill="none"
+ stroke-width="0.3"
+ stroke="#555"
+ stroke-dasharray="1 1"/>
+ </svg>
+</div>
</template>
<script lang="ts">
@@ -39,29 +42,49 @@ export default Vue.extend({
},
data() {
return {
- viewBoxX: 365,
- viewBoxY: 70,
+ viewBoxX: 100,
+ viewBoxY: 30,
pointsNote: null,
pointsReply: null,
pointsRenote: null,
- pointsTotal: null
+ pointsTotal: null,
+ span: 'day'
};
},
- created() {
- const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.notes.local.diff : d.notes.remote.diff));
+ computed: {
+ stats(): any[] {
+ return (
+ this.span == 'day' ? this.chart.perDay :
+ this.span == 'hour' ? this.chart.perHour :
+ null
+ );
+ }
+ },
+ watch: {
+ stats() {
+ this.render();
+ }
+ },
+ mounted() {
+ this.render();
+ },
+ methods: {
+ render() {
+ const peak = Math.max.apply(null, this.stats.map(d => this.type == 'local' ? d.notes.local.diff : d.notes.remote.diff));
- if (peak != 0) {
- const data = this.chart.slice().reverse().map(x => ({
- normal: this.type == 'local' ? x.notes.local.diffs.normal : x.notes.remote.diffs.normal,
- reply: this.type == 'local' ? x.notes.local.diffs.reply : x.notes.remote.diffs.reply,
- renote: this.type == 'local' ? x.notes.local.diffs.renote : x.notes.remote.diffs.renote,
- total: this.type == 'local' ? x.notes.local.diff : x.notes.remote.diff
- }));
+ if (peak != 0) {
+ const data = this.stats.slice().reverse().map(x => ({
+ normal: this.type == 'local' ? x.notes.local.diffs.normal : x.notes.remote.diffs.normal,
+ reply: this.type == 'local' ? x.notes.local.diffs.reply : x.notes.remote.diffs.reply,
+ renote: this.type == 'local' ? x.notes.local.diffs.renote : x.notes.remote.diffs.renote,
+ total: this.type == 'local' ? x.notes.local.diff : x.notes.remote.diff
+ }));
- this.pointsNote = data.map((d, i) => `${i},${(1 - (d.normal / peak)) * this.viewBoxY}`).join(' ');
- this.pointsReply = data.map((d, i) => `${i},${(1 - (d.reply / peak)) * this.viewBoxY}`).join(' ');
- this.pointsRenote = data.map((d, i) => `${i},${(1 - (d.renote / peak)) * this.viewBoxY}`).join(' ');
- this.pointsTotal = data.map((d, i) => `${i},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ');
+ this.pointsNote = data.map((d, i) => `${(this.viewBoxX / data.length) * i},${(1 - (d.normal / peak)) * this.viewBoxY}`).join(' ');
+ this.pointsReply = data.map((d, i) => `${(this.viewBoxX / data.length) * i},${(1 - (d.reply / peak)) * this.viewBoxY}`).join(' ');
+ this.pointsRenote = data.map((d, i) => `${(this.viewBoxX / data.length) * i},${(1 - (d.renote / peak)) * this.viewBoxY}`).join(' ');
+ this.pointsTotal = data.map((d, i) => `${(this.viewBoxX / data.length) * i},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ');
+ }
}
}
});
diff --git a/src/client/app/desktop/views/pages/admin/admin.users-chart.chart.vue b/src/client/app/desktop/views/pages/admin/admin.users-chart.chart.vue
index c2ab4a78e3..45ecc13929 100644
--- a/src/client/app/desktop/views/pages/admin/admin.users-chart.chart.vue
+++ b/src/client/app/desktop/views/pages/admin/admin.users-chart.chart.vue
@@ -1,11 +1,14 @@
<template>
-<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
- <polyline
- :points="points"
- fill="none"
- stroke-width="1"
- stroke="#555"/>
-</svg>
+<div>
+ <a @click="span = 'day'">Per day</a> | <a @click="span = 'hour'">Per hour</a>
+ <svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
+ <polyline
+ :points="points"
+ fill="none"
+ stroke-width="0.3"
+ stroke="#555"/>
+ </svg>
+</div>
</template>
<script lang="ts">
@@ -23,20 +26,40 @@ export default Vue.extend({
},
data() {
return {
- viewBoxX: 365,
- viewBoxY: 70,
- points: null
+ viewBoxX: 100,
+ viewBoxY: 30,
+ points: null,
+ span: 'day'
};
},
- created() {
- const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.users.local.diff : d.users.remote.diff));
+ computed: {
+ stats(): any[] {
+ return (
+ this.span == 'day' ? this.chart.perDay :
+ this.span == 'hour' ? this.chart.perHour :
+ null
+ );
+ }
+ },
+ watch: {
+ stats() {
+ this.render();
+ }
+ },
+ mounted() {
+ this.render();
+ },
+ methods: {
+ render() {
+ const peak = Math.max.apply(null, this.stats.map(d => this.type == 'local' ? d.users.local.diff : d.users.remote.diff));
- if (peak != 0) {
- const data = this.chart.slice().reverse().map(x => ({
- count: this.type == 'local' ? x.users.local.diff : x.users.remote.diff
- }));
+ if (peak != 0) {
+ const data = this.stats.slice().reverse().map(x => ({
+ count: this.type == 'local' ? x.users.local.diff : x.users.remote.diff
+ }));
- this.points = data.map((d, i) => `${i},${(1 - (d.count / peak)) * this.viewBoxY}`).join(' ');
+ this.points = data.map((d, i) => `${(this.viewBoxX / data.length) * i},${(1 - (d.count / peak)) * this.viewBoxY}`).join(' ');
+ }
}
}
});
diff --git a/src/server/api/endpoints/admin/chart.ts b/src/server/api/endpoints/admin/chart.ts
index c351c7167d..1897879d65 100644
--- a/src/server/api/endpoints/admin/chart.ts
+++ b/src/server/api/endpoints/admin/chart.ts
@@ -8,96 +8,130 @@ export const meta = {
};
export default (params: any) => new Promise(async (res, rej) => {
+ const daysRange = 365;
+ const hoursRange = 24;
+
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
+ const h = now.getHours();
- const stats = await Stats.find({
- span: 'day',
- date: {
- $gt: new Date(y - 1, m, d)
- }
- }, {
- sort: {
- date: -1
- },
- fields: {
- _id: 0
- }
- });
+ const [statsPerDay, statsPerHour] = await Promise.all([
+ Stats.find({
+ span: 'day',
+ date: {
+ $gt: new Date(y, m, d - daysRange)
+ }
+ }, {
+ sort: {
+ date: -1
+ },
+ fields: {
+ _id: 0
+ }
+ }),
+ Stats.find({
+ span: 'hour',
+ date: {
+ $gt: new Date(y, m, d, h - hoursRange)
+ }
+ }, {
+ sort: {
+ date: -1
+ },
+ fields: {
+ _id: 0
+ }
+ }),
+ ]);
- const chart: Array<Omit<IStats, '_id'>> = [];
+ const format = (src: IStats[], span: 'day' | 'hour') => {
+ const chart: Array<Omit<Omit<IStats, '_id'>, 'span'>> = [];
- for (let i = 364; i >= 0; i--) {
- const day = new Date(y, m, d - i);
+ const range =
+ span == 'day' ? daysRange :
+ span == 'hour' ? hoursRange :
+ null;
- const stat = stats.find(s => s.date.getTime() == day.getTime());
+ for (let i = (range - 1); i >= 0; i--) {
+ const current =
+ span == 'day' ? new Date(y, m, d - i) :
+ span == 'hour' ? new Date(y, m, d, h - i) :
+ null;
- if (stat) {
- chart.unshift(stat);
- } else { // 隙間埋め
- const mostRecent = stats.find(s => s.date.getTime() < day.getTime());
- if (mostRecent) {
- chart.unshift(Object.assign({}, mostRecent, {
- date: day
- }));
- } else {
- chart.unshift({
- date: day,
- span: 'day',
- users: {
- local: {
- total: 0,
- diff: 0
- },
- remote: {
- total: 0,
- diff: 0
- }
- },
- notes: {
- local: {
- total: 0,
- diff: 0,
- diffs: {
- normal: 0,
- reply: 0,
- renote: 0
+ const stat = src.find(s => s.date.getTime() == current.getTime());
+
+ if (stat) {
+ chart.unshift(stat);
+ } else { // 隙間埋め
+ const mostRecent = src.find(s => s.date.getTime() < current.getTime());
+ if (mostRecent) {
+ chart.unshift(Object.assign({}, mostRecent, {
+ date: current
+ }));
+ } else {
+ chart.unshift({
+ date: current,
+ users: {
+ local: {
+ total: 0,
+ diff: 0
+ },
+ remote: {
+ total: 0,
+ diff: 0
}
},
- remote: {
- total: 0,
- diff: 0,
- diffs: {
- normal: 0,
- reply: 0,
- renote: 0
+ notes: {
+ local: {
+ total: 0,
+ diff: 0,
+ diffs: {
+ normal: 0,
+ reply: 0,
+ renote: 0
+ }
+ },
+ remote: {
+ total: 0,
+ diff: 0,
+ diffs: {
+ normal: 0,
+ reply: 0,
+ renote: 0
+ }
}
- }
- },
- drive: {
- local: {
- totalCount: 0,
- totalSize: 0,
- diffCount: 0,
- diffSize: 0
},
- remote: {
- totalCount: 0,
- totalSize: 0,
- diffCount: 0,
- diffSize: 0
+ drive: {
+ local: {
+ totalCount: 0,
+ totalSize: 0,
+ diffCount: 0,
+ diffSize: 0
+ },
+ remote: {
+ totalCount: 0,
+ totalSize: 0,
+ diffCount: 0,
+ diffSize: 0
+ }
}
- }
- });
+ });
+ }
}
}
- }
- chart.forEach(x => {
- delete x.date;
- });
+ chart.forEach(x => {
+ delete x.date;
+ delete (x as any).span;
+ });
- res(chart);
+ return chart;
+ };
+
+ res({
+ perDay: format(statsPerDay, 'day'),
+ perHour: format(statsPerHour, 'hour')
+ });
});