diff options
author | Manoj MJ <mmj@gitlab.com> | 2019-09-09 03:38:42 +0000 |
---|---|---|
committer | Ash McKenzie <amckenzie@gitlab.com> | 2019-09-09 03:38:42 +0000 |
commit | b041321a355b507cd9329e80935e960c2b9114eb (patch) | |
tree | 5013fa7c76955750a869b5a071a1d8d8cecd9686 /app/assets/javascripts | |
parent | e3763f9cb60e7f1ddf8c40ddc4bf05747e944f9b (diff) | |
download | gitlab-ce-b041321a355b507cd9329e80935e960c2b9114eb.tar.gz |
Application Statistics API
This change implements Application
Statistics API
Diffstat (limited to 'app/assets/javascripts')
11 files changed, 178 insertions, 1 deletions
diff --git a/app/assets/javascripts/admin/statistics_panel/components/app.vue b/app/assets/javascripts/admin/statistics_panel/components/app.vue new file mode 100644 index 00000000000..29077d926cf --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/components/app.vue @@ -0,0 +1,45 @@ +<script> +import { mapState, mapGetters, mapActions } from 'vuex'; +import { GlLoadingIcon } from '@gitlab/ui'; +import statisticsLabels from '../constants'; + +export default { + components: { + GlLoadingIcon, + }, + data() { + return { + statisticsLabels, + }; + }, + computed: { + ...mapState(['isLoading', 'statistics']), + ...mapGetters(['getStatistics']), + }, + mounted() { + this.fetchStatistics(); + }, + methods: { + ...mapActions(['fetchStatistics']), + }, +}; +</script> + +<template> + <div class="info-well"> + <div class="well-segment admin-well admin-well-statistics"> + <h4>{{ __('Statistics') }}</h4> + <gl-loading-icon v-if="isLoading" size="md" class="my-3" /> + <template v-else> + <p + v-for="statistic in getStatistics(statisticsLabels)" + :key="statistic.key" + class="js-stats" + > + {{ statistic.label }} + <span class="light float-right">{{ statistic.value }}</span> + </p> + </template> + </div> + </div> +</template> diff --git a/app/assets/javascripts/admin/statistics_panel/constants.js b/app/assets/javascripts/admin/statistics_panel/constants.js new file mode 100644 index 00000000000..2dce19a3894 --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/constants.js @@ -0,0 +1,14 @@ +import { s__ } from '~/locale'; + +const statisticsLabels = { + forks: s__('AdminStatistics|Forks'), + issues: s__('AdminStatistics|Issues'), + mergeRequests: s__('AdminStatistics|Merge Requests'), + notes: s__('AdminStatistics|Notes'), + snippets: s__('AdminStatistics|Snippets'), + sshKeys: s__('AdminStatistics|SSH Keys'), + milestones: s__('AdminStatistics|Milestones'), + activeUsers: s__('AdminStatistics|Active Users'), +}; + +export default statisticsLabels; diff --git a/app/assets/javascripts/admin/statistics_panel/index.js b/app/assets/javascripts/admin/statistics_panel/index.js new file mode 100644 index 00000000000..39112e3ddc0 --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/index.js @@ -0,0 +1,22 @@ +import Vue from 'vue'; +import StatisticsPanelApp from './components/app.vue'; +import createStore from './store'; + +export default function(el) { + if (!el) { + return false; + } + + const store = createStore(); + + return new Vue({ + el, + store, + components: { + StatisticsPanelApp, + }, + render(h) { + return h(StatisticsPanelApp); + }, + }); +} diff --git a/app/assets/javascripts/admin/statistics_panel/store/actions.js b/app/assets/javascripts/admin/statistics_panel/store/actions.js new file mode 100644 index 00000000000..537025f524c --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/store/actions.js @@ -0,0 +1,28 @@ +import Api from '~/api'; +import { s__ } from '~/locale'; +import createFlash from '~/flash'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import * as types from './mutation_types'; + +export const requestStatistics = ({ commit }) => commit(types.REQUEST_STATISTICS); + +export const fetchStatistics = ({ dispatch }) => { + dispatch('requestStatistics'); + + Api.adminStatistics() + .then(({ data }) => { + dispatch('receiveStatisticsSuccess', convertObjectPropsToCamelCase(data, { deep: true })); + }) + .catch(error => dispatch('receiveStatisticsError', error)); +}; + +export const receiveStatisticsSuccess = ({ commit }, statistics) => + commit(types.RECEIVE_STATISTICS_SUCCESS, statistics); + +export const receiveStatisticsError = ({ commit }, error) => { + commit(types.RECEIVE_STATISTICS_ERROR, error); + createFlash(s__('AdminDashboard|Error loading the statistics. Please try again')); +}; + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/admin/statistics_panel/store/getters.js b/app/assets/javascripts/admin/statistics_panel/store/getters.js new file mode 100644 index 00000000000..24437bc76bf --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/store/getters.js @@ -0,0 +1,17 @@ +/** + * Merges the statisticsLabels with the state's data + * and returns an array of the following form: + * [{ key: "forks", label: "Forks", value: 50 }] + */ +export const getStatistics = state => labels => + Object.keys(labels).map(key => { + const result = { + key, + label: labels[key], + value: state.statistics && state.statistics[key] ? state.statistics[key] : null, + }; + return result; + }); + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/admin/statistics_panel/store/index.js b/app/assets/javascripts/admin/statistics_panel/store/index.js new file mode 100644 index 00000000000..ece9e6419dd --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/store/index.js @@ -0,0 +1,16 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import * as actions from './actions'; +import * as getters from './getters'; +import mutations from './mutations'; +import state from './state'; + +Vue.use(Vuex); + +export default () => + new Vuex.Store({ + actions, + getters, + mutations, + state: state(), + }); diff --git a/app/assets/javascripts/admin/statistics_panel/store/mutation_types.js b/app/assets/javascripts/admin/statistics_panel/store/mutation_types.js new file mode 100644 index 00000000000..4e0ca4ed3cd --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/store/mutation_types.js @@ -0,0 +1,3 @@ +export const REQUEST_STATISTICS = 'REQUEST_STATISTICS'; +export const RECEIVE_STATISTICS_SUCCESS = 'RECEIVE_STATISTICS_SUCCESS'; +export const RECEIVE_STATISTICS_ERROR = 'RECEIVE_STATISTICS_ERROR'; diff --git a/app/assets/javascripts/admin/statistics_panel/store/mutations.js b/app/assets/javascripts/admin/statistics_panel/store/mutations.js new file mode 100644 index 00000000000..d0fac5cfbab --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/store/mutations.js @@ -0,0 +1,16 @@ +import * as types from './mutation_types'; + +export default { + [types.REQUEST_STATISTICS](state) { + state.isLoading = true; + }, + [types.RECEIVE_STATISTICS_SUCCESS](state, data) { + state.isLoading = false; + state.error = null; + state.statistics = data; + }, + [types.RECEIVE_STATISTICS_ERROR](state, error) { + state.isLoading = false; + state.error = error; + }, +}; diff --git a/app/assets/javascripts/admin/statistics_panel/store/state.js b/app/assets/javascripts/admin/statistics_panel/store/state.js new file mode 100644 index 00000000000..f2f2dc0a4d2 --- /dev/null +++ b/app/assets/javascripts/admin/statistics_panel/store/state.js @@ -0,0 +1,5 @@ +export default () => ({ + error: null, + isLoading: false, + statistics: null, +}); diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 136ffdf8b9d..1d97ad5ec11 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -36,6 +36,7 @@ const Api = { branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch', createBranchPath: '/api/:version/projects/:id/repository/branches', releasesPath: '/api/:version/projects/:id/releases', + adminStatisticsPath: 'api/:version/application/statistics', group(groupId, callback) { const url = Api.buildUrl(Api.groupPath).replace(':id', groupId); @@ -376,6 +377,11 @@ const Api = { return axios.get(url); }, + adminStatistics() { + const url = Api.buildUrl(this.adminStatisticsPath); + return axios.get(url); + }, + buildUrl(url) { return joinPaths(gon.relative_url_root || '', url.replace(':version', gon.api_version)); }, diff --git a/app/assets/javascripts/pages/admin/index.js b/app/assets/javascripts/pages/admin/index.js index 8a32556f06c..74f2eead755 100644 --- a/app/assets/javascripts/pages/admin/index.js +++ b/app/assets/javascripts/pages/admin/index.js @@ -1,3 +1,8 @@ import initAdmin from './admin'; +import initAdminStatisticsPanel from '../../admin/statistics_panel/index'; -document.addEventListener('DOMContentLoaded', initAdmin()); +document.addEventListener('DOMContentLoaded', () => { + const statisticsPanelContainer = document.getElementById('js-admin-statistics-container'); + initAdmin(); + initAdminStatisticsPanel(statisticsPanelContainer); +}); |