diff --git a/Gulpfile.js b/Gulpfile.js index 9cbfec2d15..9f5c913eae 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -116,7 +116,8 @@ function jsPackages() { require.resolve('jquery/dist/jquery.min.js'), require.resolve('moment/min/moment.min.js'), require.resolve('moment/locale/fr.js'), - require.resolve('chart.js/dist/Chart.min.js'), + require.resolve('chartjs-adapter-moment/dist/chartjs-adapter-moment.min.js'), + require.resolve('chart.js/dist/chart.min.js'), require.resolve('easymde/dist/easymde.min.js') ]) .pipe(gulp.dest('dist/js/')) diff --git a/assets/js/charts.js b/assets/js/charts.js index 7a1d3f2133..c9135d1b36 100644 --- a/assets/js/charts.js +++ b/assets/js/charts.js @@ -1,6 +1,4 @@ -(function($) { - 'use strict' - +(function() { /** * HSV to RGB color conversion * @@ -54,10 +52,11 @@ var basicOptions = { scales: { - xAxes: [{ + x: { type: 'time', time: { parser: 'DD/MM/YYYY', + tooltipFormat: 'DD/MM/YYYY', displayFormats: { hour: 'DD MMM', day: 'DD MMM', @@ -67,25 +66,28 @@ year: 'YYYY' } } - }], - yAxes: [{ - ticks: { - beginAtZero: true - } - }] + }, + y: { + beginAtZero: true + } }, responsive: true } var charts = [] - function setupChart($object, formatter) { - var $dataX = $object.data('time') + var chartFormatters = { + 'view-graph': null, + 'visit-time-graph': Math.round, + 'users-graph': null + } + function setupChart(chartEl, formatter) { + var dataX = JSON.parse(chartEl.getAttribute('data-time')) var times = [] - $dataX.forEach(function(element) { + dataX.forEach(function(element) { times.push(window.moment(element).format('DD/MM/YYYY')) }) - var allObjectData = $object.data() + var allObjectData = chartEl.dataset var data = [] // Count how many graphs are displayed var nbColors = 0 @@ -97,11 +99,12 @@ var n = 0 for (var o in allObjectData) { if (o.indexOf('views') > -1) { - var label = $object.data('label-' + o) + var label = chartEl.getAttribute('data-label-' + o) var color = hsvToRgb(n, 100, 80) + var d = JSON.parse(allObjectData[o]) data.push({ label: label, - data: formatter ? allObjectData[o].map(formatter) : allObjectData[o], + data: formatter ? d.map(formatter) : d, fill: false, backgroundColor: 'rgba(' + color.join(',') + ', 1)', borderColor: 'rgba(' + color.join(',') + ', 0.70)', @@ -117,9 +120,19 @@ labels: times, datasets: data }, - options: basicOptions + options: { + ...basicOptions, + scales: { + y: { + title: { + display: true, + text: chartEl.getAttribute('data-y-label') + } + } + } + } } - charts.push(new window.Chart($object, config)) + charts.push(new window.Chart(chartEl, config)) } // Switching between a graph with lines and a graph with bars @@ -130,18 +143,21 @@ localStorage.setItem('graphType', 'line') // default value } - $('#graph_type_toogle').click(function() { - if (localStorage.getItem('graphType') === 'line') { - localStorage.setItem('graphType', 'bar') - $(this).text(switchToLine) - } else { - localStorage.setItem('graphType', 'line') - $(this).text(switchToBar) - } - clearCharts() - drawCharts() - }) - $('#graph_type_toogle').text(localStorage.getItem('graphType') === 'line' ? switchToBar : switchToLine) + var graphTypeToggleEl = document.getElementById('graph_type_toggle') + if (graphTypeToggleEl !== null) { + graphTypeToggleEl.addEventListener('click', function() { + if (localStorage.getItem('graphType') === 'line') { + localStorage.setItem('graphType', 'bar') + graphTypeToggleEl.textContent = switchToLine + } else { + localStorage.setItem('graphType', 'line') + graphTypeToggleEl.textContent = switchToBar + } + clearCharts() + drawCharts() + }) + graphTypeToggleEl.textContent = localStorage.getItem('graphType') === 'line' ? switchToBar : switchToLine + } // Clearing charts function clearCharts() { @@ -152,43 +168,37 @@ // Drawing charts function drawCharts() { - if ($('#view-graph').length) { - setupChart($('#view-graph')) - } - if ($('#visit-time-graph').length) { - setupChart($('#visit-time-graph'), Math.round) - } - if ($('#users-graph').length) { - setupChart($('#users-graph')) - } - if ($('#new-users-graph').length) { - setupChart($('#new-users-graph')) - } - if ($('#sessions-graph').length) { - setupChart($('#sessions-graph')) + for (var g in chartFormatters) { + var el = document.getElementById(g) + if (el !== null) { + setupChart(el, chartFormatters[g]) + } } } drawCharts() // Tab management - function displayTab(tab) { + function displayTab(tabEl) { + if (tabEl === null) { + return + } // Hide all the tabs - $('.tabcontent').each(function() { - $(this).hide() + document.querySelectorAll('.tabcontent').forEach(function(el) { + el.style.display = 'none' }) // Remove "active" info from links - $('.tablinks').each(function() { - $(this).removeClass('active') + document.querySelectorAll('.tablinks').forEach(function(el) { + el.classList.remove('active') }) // Show current tab and add "active" class to the link - $('#' + $(tab).attr('id') + '-content').show() - $(tab).addClass('active') + document.getElementById(tabEl.getAttribute('id') + '-content').style.display = 'block' + tabEl.classList.add('active') } - $('.tablinks').each(function() { - $(this).click(function() { - displayTab($(this)) + document.querySelectorAll('.tablinks').forEach(function(el) { + el.addEventListener('click', function(e) { + displayTab(el) }) }) - displayTab($('.tablinks').first()) -})(jQuery) + displayTab(document.querySelector('.tablinks')) +})() diff --git a/assets/scss/pages/_stats.scss b/assets/scss/pages/_stats.scss index e3da8c7756..0b130f004f 100644 --- a/assets/scss/pages/_stats.scss +++ b/assets/scss/pages/_stats.scss @@ -38,7 +38,7 @@ /* Style the tab content */ .tabcontent { - display: none; + /* Tab has to be displayed by default, otherwise Chart.js doesn't render the graph. */ padding: $length-6 $length-12; diff --git a/package.json b/package.json index 468b052eae..53cafec939 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "homepage": "https://github.com/zestedesavoir/zds-site", "dependencies": { "autoprefixer": "10.2.5", - "chart.js": "2.9.4", + "chart.js": "3.5.1", + "chartjs-adapter-moment": "1.0.0", "cssnano": "5.0.4", "del": "6.0.0", "easymde": "2.10.2-360.0", diff --git a/templates/misc/graph.part.html b/templates/misc/graph.part.html index 25794db78f..f7960ecebe 100644 --- a/templates/misc/graph.part.html +++ b/templates/misc/graph.part.html @@ -8,6 +8,7 @@

{% trans graph_title %}

- + + {% endblock %} {% block content_out %} @@ -46,9 +47,9 @@

{% trans "Nombre de visiteurs uniques" %} - {% include "misc/graph.part.html" with tab_name="tab-view-graph-content" graph_title="Évolution des pages vues sur le contenu" canvas_id="view-graph" report_key="nb_hits" %} - {% include "misc/graph.part.html" with tab_name="tab-visit-time-graph-content" graph_title="Évolution du temps moyen lecture (en secondes)" canvas_id="visit-time-graph" report_key="avg_time_on_page" %} - {% include "misc/graph.part.html" with tab_name="tab-users-graph-content" graph_title="Évolution du nombre de visiteurs uniques" canvas_id="users-graph" report_key="nb_uniq_visitors" %} + {% include "misc/graph.part.html" with tab_name="tab-view-graph-content" graph_title="Évolution des pages vues sur le contenu" canvas_id="view-graph" report_key="nb_hits" y_label="Nombre de pages" %} + {% include "misc/graph.part.html" with tab_name="tab-visit-time-graph-content" graph_title="Évolution du temps moyen lecture (en secondes)" canvas_id="visit-time-graph" report_key="avg_time_on_page" y_label="Secondes" %} + {% include "misc/graph.part.html" with tab_name="tab-users-graph-content" graph_title="Évolution du nombre de visiteurs uniques" canvas_id="users-graph" report_key="nb_uniq_visitors" y_label="Nombre de visiteurs" %} {% if cumulative_stats %} @@ -237,7 +238,7 @@

{% trans "Échelle de temps" %}

Type de graphe

diff --git a/yarn.lock b/yarn.lock index 2846cd548e..feb34ed0db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -773,28 +773,15 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chart.js@2.9.4: - version "2.9.4" - resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684" - integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A== - dependencies: - chartjs-color "^2.1.0" - moment "^2.10.2" - -chartjs-color-string@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71" - integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A== - dependencies: - color-name "^1.0.0" +chart.js@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.5.1.tgz#73e24d23a4134a70ccdb5e79a917f156b6f3644a" + integrity sha512-m5kzt72I1WQ9LILwQC4syla/LD/N413RYv2Dx2nnTkRS9iv/ey1xLTt0DnPc/eWV4zI+BgEgDYBIzbQhZHc/PQ== -chartjs-color@^2.1.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0" - integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w== - dependencies: - chartjs-color-string "^0.6.0" - color-convert "^1.9.3" +chartjs-adapter-moment@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.0.tgz#9174b1093c68bcfe285aff24f7388ad60d44e8f7" + integrity sha512-PqlerEvQcc5hZLQ/NQWgBxgVQ4TRdvkW3c/t+SUEQSj78ia3hgLkf2VZ2yGJtltNbEEFyYGm+cA6XXevodYvWA== "chokidar@>=3.0.0 <4.0.0": version "3.5.1" @@ -950,7 +937,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0, color-convert@^1.9.3: +color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -969,7 +956,7 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0, color-name@~1.1.4: +color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -4026,7 +4013,7 @@ mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "^1.2.5" -moment@2.29.1, moment@^2.10.2: +moment@2.29.1: version "2.29.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==