From c1de536cc0468bcb790e2e949c2a78784540ef23 Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Thu, 19 Dec 2019 19:55:24 +0300 Subject: [PATCH] Add stats page (status counts by scope) --- CHANGELOG.md | 1 + README.md | 1 + src/api/{peers.js => instance.js} | 9 ++++ src/lang/en.js | 12 ++++- src/router/index.js | 15 ++++++ src/store/getters.js | 3 +- src/store/index.js | 4 +- src/store/modules/instance.js | 40 ++++++++++++++++ src/store/modules/peers.js | 28 ------------ src/views/stats/index.vue | 76 +++++++++++++++++++++++++++++++ src/views/statuses/index.vue | 2 +- 11 files changed, 158 insertions(+), 33 deletions(-) rename src/api/{peers.js => instance.js} (66%) create mode 100644 src/store/modules/instance.js delete mode 100644 src/store/modules/peers.js create mode 100644 src/views/stats/index.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 9026cec5..71b111d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Ability to confirm users' emails and resend confirmation emails - Report notes - Ability to moderate users on the statuses page +- Stats page: status counts are displayed here ### Fixed diff --git a/README.md b/README.md index 84ce067d..413802c2 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Features, that can be disabled: - moderation log: `DISABLED_FEATURES: '["moderationLog"]'` - settings: `DISABLED_FEATURES: '["settings"]'` - emoji packs: `DISABLED_FEATURES: '["emojiPacks"]'` +- stats: `DISABLED_FEATURES: '["stats"]'` Of course, you can disable multiple features just by adding to the array, e.g. `DISABLED_FEATURES: '["emojiPacks", "settings"]'` will have both emoji packs and settings disabled. diff --git a/src/api/peers.js b/src/api/instance.js similarity index 66% rename from src/api/peers.js rename to src/api/instance.js index 4b80d7ab..a4e3ad9b 100644 --- a/src/api/peers.js +++ b/src/api/instance.js @@ -11,4 +11,13 @@ export async function fetchPeers(authHost, token) { }) } +export async function fetchInstanceInfo(authHost, token) { + return await request({ + baseURL: baseName(authHost), + url: `/api/v1/instance`, + method: 'get', + headers: authHeaders(token) + }) +} + const authHeaders = (token) => token ? { 'Authorization': `Bearer ${getToken()}` } : {} diff --git a/src/lang/en.js b/src/lang/en.js index 3dcd9bdd..d9b696b5 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -67,7 +67,8 @@ export default { reports: 'Reports', settings: 'Settings', moderationLog: 'Moderation Log', - 'emoji-packs': 'Emoji packs' + 'emoji-packs': 'Emoji packs', + stats: 'Stats' }, navbar: { logOut: 'Log Out', @@ -432,5 +433,14 @@ export default { emailSent: 'Invite was sent', submitFormError: 'There are invalid values in the form. Please fix them before continuing.', inviteViaEmailAlert: 'To send invite via email make sure to enable `invites_enabled` and disable `registrations_open`' + }, + stats: { + stats: 'Instance stats', + statusCounts: 'Status counts', + all: 'All', + public: 'Public', + unlisted: 'Unlisted', + direct: 'Direct', + private: 'Private' } } diff --git a/src/router/index.js b/src/router/index.js index 8a7f9e36..c4b48385 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -77,6 +77,20 @@ const moderationLog = { ] } +const statsDisabled = disabledFeatures.includes('stats') +const stats = { + path: '/stats', + component: Layout, + children: [ + { + path: 'index', + component: () => import('@/views/stats/index'), + name: 'Stats', + meta: { title: 'stats', icon: 'chart', noCache: true } + } + ] +} + export const constantRouterMap = [ { path: '/redirect', @@ -145,6 +159,7 @@ export const asyncRouterMap = [ ...(invitesDisabled ? [] : [invites]), ...(moderationLogDisabled ? [] : [moderationLog]), ...(settingsDisabled ? [] : [settings]), + ...(statsDisabled ? [] : [stats]), { path: '/users/:id', component: Layout, diff --git a/src/store/getters.js b/src/store/getters.js index 159fb48c..0722b4c2 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -49,7 +49,7 @@ const getters = { http: state => state.settings.settings['http'], httpSecurity: state => state.settings.settings['http_security'], instance: state => state.settings.settings['instance'], - instances: state => state.peers.fetchedPeers, + instances: state => state.instance.fetchedPeers, kocaptcha: state => state.settings.settings['Pleroma.Captcha.Kocaptcha'], level: state => state.settings.settings['level'], ldap: state => state.settings.settings['ldap'], @@ -84,6 +84,7 @@ const getters = { suggestions: state => state.settings.settings['suggestions'], scheduledActivity: state => state.settings.settings['Pleroma.ScheduledActivity'], statuses: state => state.status.fetchedStatuses, + statusCounts: state => state.instance.fetchedStatusCounts, teslaAdapter: state => state.settings.settings['adapter'], twitter: state => state.settings.settings['Ueberauth.Strategy.Twitter.OAuth'], ueberauth: state => state.settings.settings['Ueberauth'], diff --git a/src/store/index.js b/src/store/index.js index 586f2b07..bb654676 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -4,7 +4,7 @@ import app from './modules/app' import errorLog from './modules/errorLog' import moderationLog from './modules/moderationLog' import invites from './modules/invites' -import peers from './modules/peers' +import instance from './modules/instance' import permission from './modules/permission' import relays from './modules/relays' import reports from './modules/reports' @@ -25,7 +25,7 @@ const store = new Vuex.Store({ errorLog, moderationLog, invites, - peers, + instance, permission, relays, reports, diff --git a/src/store/modules/instance.js b/src/store/modules/instance.js new file mode 100644 index 00000000..cec33c91 --- /dev/null +++ b/src/store/modules/instance.js @@ -0,0 +1,40 @@ +import { fetchPeers, fetchInstanceInfo } from '@/api/instance' + +const instance = { + state: { + fetchedPeers: [], + peersLoading: true, + fetchedStatusCounts: {}, + statusCountsLoading: true + }, + mutations: { + SET_PEERS: (state, peers) => { + state.fetchedPeers = peers + }, + SET_PEERS_LOADING: (state, status) => { + state.peersLoading = status + }, + SET_STATUS_COUNTS: (state, counts) => { + state.fetchedStatusCounts = counts + }, + SET_STATUS_COUNTS_LOADING: (state, status) => { + state.statusCountsLoading = status + } + }, + actions: { + async FetchPeers({ commit, getters }) { + const peers = await fetchPeers(getters.authHost, getters.token) + + commit('SET_PEERS', peers.data) + commit('SET_PEERS_LOADING', false) + }, + async FetchStatusCounts({ commit, getters }) { + const info = await fetchInstanceInfo(getters.authHost, getters.token) + + commit('SET_STATUS_COUNTS', info.data.stats.status_count) + commit('SET_STATUS_COUNTS_LOADING', false) + } + } +} + +export default instance diff --git a/src/store/modules/peers.js b/src/store/modules/peers.js deleted file mode 100644 index fa37a1d0..00000000 --- a/src/store/modules/peers.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fetchPeers } from '@/api/peers' - -const peers = { - state: { - fetchedPeers: [], - loading: true - }, - - mutations: { - SET_PEERS: (state, peers) => { - state.fetchedPeers = peers - }, - SET_LOADING: (state, status) => { - state.loading = status - } - }, - - actions: { - async FetchPeers({ commit, getters }) { - const peers = await fetchPeers(getters.authHost, getters.token) - - commit('SET_PEERS', peers.data) - commit('SET_LOADING', false) - } - } -} - -export default peers diff --git a/src/views/stats/index.vue b/src/views/stats/index.vue new file mode 100644 index 00000000..7b58b0af --- /dev/null +++ b/src/views/stats/index.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/views/statuses/index.vue b/src/views/statuses/index.vue index 408d3e24..0651d247 100644 --- a/src/views/statuses/index.vue +++ b/src/views/statuses/index.vue @@ -49,7 +49,7 @@ export default { }, computed: { loadingPeers() { - return this.$store.state.peers.loading + return this.$store.state.instance.peersLoading }, ...mapGetters([ 'instances',