Commit ff070d69 authored by Martin Wortschack's avatar Martin Wortschack Committed by Martin Wortschack

Add instance statistics counts

- Adds a metric card for
the several instance statistics
counts.
parent c6478b70
<script>
import InstanceCounts from './instance_counts.vue';
export default {
name: 'InstanceStatisticsApp',
components: {
InstanceCounts,
},
};
</script>
<template>
<instance-counts />
</template>
<script>
import * as Sentry from '@sentry/browser';
import { s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
import instanceStatisticsCountQuery from '../graphql/queries/instance_statistics_count.query.graphql';
const defaultPrecision = 0;
export default {
name: 'InstanceCounts',
components: {
MetricCard,
},
data() {
return {
counts: [],
};
},
apollo: {
counts: {
query: instanceStatisticsCountQuery,
update(data) {
return Object.entries(data).map(([key, obj]) => {
const label = this.$options.i18n.labels[key];
const formatter = getFormatter(SUPPORTED_FORMATS.number);
const value = obj.nodes?.length ? formatter(obj.nodes[0].count, defaultPrecision) : null;
return {
key,
value,
label,
};
});
},
error(error) {
createFlash(this.$options.i18n.loadCountsError);
Sentry.captureException(error);
},
},
},
i18n: {
labels: {
users: s__('InstanceStatistics|Users'),
projects: s__('InstanceStatistics|Projects'),
groups: s__('InstanceStatistics|Groups'),
issues: s__('InstanceStatistics|Issues'),
mergeRequests: s__('InstanceStatistics|Merge Requests'),
pipelines: s__('InstanceStatistics|Pipelines'),
},
loadCountsError: s__('Could not load instance counts. Please refresh the page to try again.'),
},
};
</script>
<template>
<metric-card
:title="__('Instance Statistics')"
:metrics="counts"
:is-loading="$apollo.queries.counts.loading"
class="gl-mt-4"
/>
</template>
query getInstanceCounts {
projects: instanceStatisticsMeasurements(identifier: PROJECTS, first: 1) {
nodes {
count
}
}
groups: instanceStatisticsMeasurements(identifier: GROUPS, first: 1) {
nodes {
count
}
}
users: instanceStatisticsMeasurements(identifier: USERS, first: 1) {
nodes {
count
}
}
issues: instanceStatisticsMeasurements(identifier: ISSUES, first: 1) {
nodes {
count
}
}
mergeRequests: instanceStatisticsMeasurements(identifier: MERGE_REQUESTS, first: 1) {
nodes {
count
}
}
pipelines: instanceStatisticsMeasurements(identifier: PIPELINES, first: 1) {
nodes {
count
}
}
}
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import InstanceStatisticsApp from './components/app.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
export default () => {
const el = document.getElementById('js-instance-statistics-app');
if (!el) return false;
return new Vue({
el,
apolloProvider,
render(h) {
return h(InstanceStatisticsApp);
},
});
};
import initInstanceStatisticsApp from '~/analytics/instance_statistics';
document.addEventListener('DOMContentLoaded', () => initInstanceStatisticsApp());
<script>
import { OVERVIEW_METRICS } from '../constants';
import TimeMetricsCard from './time_metrics_card.vue';
import MetricCard from '../../shared/components/metric_card.vue';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
export default {
name: 'OverviewActivity',
......
......@@ -2,7 +2,7 @@
import Api from 'ee/api';
import { sprintf, __, s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import MetricCard from '../../shared/components/metric_card.vue';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
import { removeFlash, prepareTimeMetricsData } from '../utils';
import { OVERVIEW_METRICS } from '../constants';
......
......@@ -2,7 +2,7 @@
import Api from 'ee/api';
import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import MetricCard from '../../shared/components/metric_card.vue';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
export default {
name: 'GroupActivityCard',
......
......@@ -2,8 +2,8 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Api from 'ee/api';
import GroupActivityCard from 'ee/analytics/group_analytics/components/group_activity_card.vue';
import MetricCard from 'ee/analytics/shared/components/metric_card.vue';
import waitForPromises from 'helpers/wait_for_promises';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
import axios from '~/lib/utils/axios_utils';
const TEST_GROUP_ID = 'gitlab-org';
......
......@@ -8,8 +8,6 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-09-17 11:26-0400\n"
"PO-Revision-Date: 2020-09-17 11:26-0400\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
......@@ -7184,6 +7182,9 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
msgid "Could not remove the trigger."
msgstr ""
......@@ -13583,6 +13584,24 @@ msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
msgid "InstanceStatistics|Groups"
msgstr ""
msgid "InstanceStatistics|Issues"
msgstr ""
msgid "InstanceStatistics|Merge Requests"
msgstr ""
msgid "InstanceStatistics|Pipelines"
msgstr ""
msgid "InstanceStatistics|Projects"
msgstr ""
msgid "InstanceStatistics|Users"
msgstr ""
msgid "Integration"
msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import InstanceStatisticsApp from '~/analytics/instance_statistics/components/app.vue';
import InstanceCounts from '~/analytics/instance_statistics/components//instance_counts.vue';
describe('InstanceStatisticsApp', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMount(InstanceStatisticsApp);
};
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('displays the instance counts component', () => {
expect(wrapper.find(InstanceCounts).exists()).toBe(true);
});
});
import { shallowMount } from '@vue/test-utils';
import InstanceCounts from '~/analytics/instance_statistics/components/instance_counts.vue';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
import countsMockData from '../mock_data';
describe('InstanceCounts', () => {
let wrapper;
const createComponent = ({ loading = false, data = {} } = {}) => {
const $apollo = {
queries: {
counts: {
loading,
},
},
};
wrapper = shallowMount(InstanceCounts, {
mocks: { $apollo },
data() {
return {
...data,
};
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const findMetricCard = () => wrapper.find(MetricCard);
describe('while loading', () => {
beforeEach(() => {
createComponent({ loading: true });
});
it('displays the metric card with isLoading=true', () => {
expect(findMetricCard().props('isLoading')).toBe(true);
});
});
describe('with data', () => {
beforeEach(() => {
createComponent({ data: { counts: countsMockData } });
});
it('passes the counts data to the metric card', () => {
expect(findMetricCard().props('metrics')).toEqual(countsMockData);
});
});
});
export default [
{ key: 'projects', value: 10, label: 'Projects' },
{ key: 'groups', value: 20, label: 'Group' },
];
import { mount } from '@vue/test-utils';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import MetricCard from 'ee/analytics/shared/components/metric_card.vue';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
const metrics = [
{ key: 'first_metric', value: 10, label: 'First metric', unit: 'days', link: 'some_link' },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment