Commit 41f2f209 authored by Phil Hughes's avatar Phil Hughes

Merge branch '196182-convert-repository-charts-to-echarts' into 'master'

Resolve "Convert Repository Charts to ECharts"

Closes #196182

See merge request gitlab-org/gitlab!24786
parents 196b1112 4fbec2c1
import $ from 'jquery';
import Chart from 'chart.js';
import { barChartOptions, pieChartOptions } from '~/lib/utils/chart_utils';
import Vue from 'vue';
import { __ } from '~/locale';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
import SeriesDataMixin from './series_data_mixin';
document.addEventListener('DOMContentLoaded', () => {
const projectChartData = JSON.parse(document.getElementById('projectChartData').innerHTML);
const languagesContainer = document.getElementById('js-languages-chart');
const monthContainer = document.getElementById('js-month-chart');
const weekdayContainer = document.getElementById('js-weekday-chart');
const hourContainer = document.getElementById('js-hour-chart');
const barChart = (selector, data) => {
// get selector by context
const ctx = selector.get(0).getContext('2d');
// pointing parent container to make chart.js inherit its width
const container = $(selector).parent();
selector.attr('width', $(container).width());
// Scale fonts if window width lower than 768px (iPad portrait)
const shouldAdjustFontSize = window.innerWidth < 768;
return new Chart(ctx, {
type: 'bar',
data,
options: barChartOptions(shouldAdjustFontSize),
});
};
const pieChart = (context, data) => {
const options = pieChartOptions();
return new Chart(context, {
type: 'pie',
data,
options,
});
};
const chartData = data => ({
labels: Object.keys(data),
datasets: [
{
backgroundColor: 'rgba(220,220,220,0.5)',
borderColor: 'rgba(220,220,220,1)',
borderWidth: 1,
data: Object.values(data),
},
],
});
const LANGUAGE_CHART_HEIGHT = 300;
const reorderWeekDays = (weekDays, firstDayOfWeek = 0) => {
if (firstDayOfWeek === 0) {
......@@ -58,28 +26,115 @@ document.addEventListener('DOMContentLoaded', () => {
}, {});
};
const hourData = chartData(projectChartData.hour);
barChart($('#hour-chart'), hourData);
// eslint-disable-next-line no-new
new Vue({
el: languagesContainer,
components: {
GlColumnChart,
},
data() {
return {
chartData: JSON.parse(languagesContainer.dataset.chartData),
};
},
computed: {
seriesData() {
return { full: this.chartData.map(d => [d.label, d.value]) };
},
},
render(h) {
return h(GlColumnChart, {
props: {
data: this.seriesData,
xAxisTitle: __('Used programming language'),
yAxisTitle: __('Percentage'),
xAxisType: 'category',
},
attrs: {
height: LANGUAGE_CHART_HEIGHT,
},
});
},
});
const weekDays = reorderWeekDays(projectChartData.weekDays, gon.first_day_of_week);
const dayData = chartData(weekDays);
barChart($('#weekday-chart'), dayData);
// eslint-disable-next-line no-new
new Vue({
el: monthContainer,
components: {
GlColumnChart,
},
mixins: [SeriesDataMixin],
data() {
return {
chartData: JSON.parse(monthContainer.dataset.chartData),
};
},
render(h) {
return h(GlColumnChart, {
props: {
data: this.seriesData,
xAxisTitle: __('Day of month'),
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
},
});
},
});
const monthData = chartData(projectChartData.month);
barChart($('#month-chart'), monthData);
// eslint-disable-next-line no-new
new Vue({
el: weekdayContainer,
components: {
GlColumnChart,
},
data() {
return {
chartData: JSON.parse(weekdayContainer.dataset.chartData),
};
},
computed: {
seriesData() {
const weekDays = reorderWeekDays(this.chartData, gon.first_day_of_week);
const data = Object.keys(weekDays).reduce((acc, key) => {
acc.push([key, weekDays[key]]);
return acc;
}, []);
return { full: data };
},
},
render(h) {
return h(GlColumnChart, {
props: {
data: this.seriesData,
xAxisTitle: __('Weekday'),
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
},
});
},
});
const data = {
datasets: [
{
data: projectChartData.languages.map(x => x.value),
backgroundColor: projectChartData.languages.map(x => x.color),
hoverBackgroundColor: projectChartData.languages.map(x => x.highlight),
},
],
labels: projectChartData.languages.map(x => x.label),
// eslint-disable-next-line no-new
new Vue({
el: hourContainer,
components: {
GlColumnChart,
},
mixins: [SeriesDataMixin],
data() {
return {
chartData: JSON.parse(hourContainer.dataset.chartData),
};
const ctx = $('#languages-chart')
.get(0)
.getContext('2d');
pieChart(ctx, data);
},
render(h) {
return h(GlColumnChart, {
props: {
data: this.seriesData,
xAxisTitle: __('Hour (UTC)'),
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
},
});
},
});
});
export default {
computed: {
seriesData() {
const data = Object.keys(this.chartData).reduce((acc, key) => {
acc.push([key, this.chartData[key]]);
return acc;
}, []);
return { full: data };
},
},
};
......@@ -7,20 +7,7 @@
%p
= _("Measured in bytes of code. Excludes generated and vendored code.")
.row
.col-md-4
%ul.bordered-list
- @languages.each do |language|
%li
%span{ style: "color: #{language[:color]}" }
= icon('circle')
&nbsp;
= language[:label]
.float-right
= language[:value]
\%
.col-md-8
%canvas#languages-chart{ height: 400 }
#js-languages-chart{ data: { chart_data: @languages.to_json.html_safe } }
.repo-charts
.sub-header-block.border-top
......@@ -60,27 +47,18 @@
%p.slead
= _("Commits per day of month")
%div
%canvas#month-chart
#js-month-chart{ data: { chart_data: @commits_per_month.to_json.html_safe } }
.row
.col-md-6
.col-md-6
%p.slead
= _("Commits per weekday")
%div
%canvas#weekday-chart
#js-weekday-chart{ data: { chart_data: @commits_per_week_days.to_json.html_safe } }
.row
.col-md-6
.col-md-6
%p.slead
= _("Commits per day hour (UTC)")
%div
%canvas#hour-chart
-# haml-lint:disable InlineJavaScript
%script#projectChartData{ type: "application/json" }
- projectChartData = {};
- projectChartData['hour'] = @commits_per_time
- projectChartData['weekDays'] = @commits_per_week_days
- projectChartData['month'] = @commits_per_month
- projectChartData['languages'] = @languages
= projectChartData.to_json.html_safe
#js-hour-chart{ data: { chart_data: @commits_per_time.to_json.html_safe } }
......@@ -5996,6 +5996,9 @@ msgstr ""
msgid "Date range cannot exceed %{maxDateRange} days."
msgstr ""
msgid "Day of month"
msgstr ""
msgid "DayTitle|F"
msgstr ""
......@@ -10004,6 +10007,9 @@ msgstr ""
msgid "Hook was successfully updated."
msgstr ""
msgid "Hour (UTC)"
msgstr ""
msgid "Housekeeping"
msgstr ""
......@@ -12803,6 +12809,9 @@ msgstr ""
msgid "No, not interested right now"
msgstr ""
msgid "No. of commits"
msgstr ""
msgid "Nobody has starred this repository yet"
msgstr ""
......@@ -13531,6 +13540,9 @@ msgstr ""
msgid "People without permission will never get a notification."
msgstr ""
msgid "Percentage"
msgstr ""
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
......@@ -20797,6 +20809,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
msgid "Used programming language"
msgstr ""
msgid "Used to help configure your identity provider"
msgstr ""
......@@ -21486,6 +21501,9 @@ msgstr ""
msgid "Wednesday"
msgstr ""
msgid "Weekday"
msgstr ""
msgid "Weeks"
msgstr ""
......
......@@ -22,20 +22,12 @@ describe 'Project Graph', :js do
end
end
shared_examples 'page should have languages graphs' do
it 'renders languages' do
expect(page).to have_content(/Ruby 66.* %/)
expect(page).to have_content(/JavaScript 22.* %/)
end
end
context 'commits graph' do
before do
visit commits_project_graph_path(project, 'master')
end
it_behaves_like 'page should have commits graphs'
it_behaves_like 'page should have languages graphs'
end
context 'languages graph' do
......@@ -44,7 +36,6 @@ describe 'Project Graph', :js do
end
it_behaves_like 'page should have commits graphs'
it_behaves_like 'page should have languages graphs'
end
context 'charts graph' do
......@@ -53,7 +44,6 @@ describe 'Project Graph', :js do
end
it_behaves_like 'page should have commits graphs'
it_behaves_like 'page should have languages graphs'
end
context 'chart graph with HTML escaped branch name' do
......
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