diff --git a/install/package.json b/install/package.json index 4a2a6275c5..119599a907 100644 --- a/install/package.json +++ b/install/package.json @@ -45,7 +45,7 @@ "bootstrap": "5.3.2", "bootswatch": "5.3.2", "chalk": "4.1.2", - "chart.js": "2.9.4", + "chart.js": "4.4.0", "cli-graph": "3.2.2", "clipboard": "2.0.11", "colors": "1.4.0", diff --git a/public/scss/admin/general/dashboard.scss b/public/scss/admin/general/dashboard.scss index cecbbb1dbe..2cfc461a0e 100644 --- a/public/scss/admin/general/dashboard.scss +++ b/public/scss/admin/general/dashboard.scss @@ -1,6 +1,4 @@ .dashboard { - max-width: 1680px; - .card { max-width: 100% !important; } @@ -9,114 +7,70 @@ position: relative; background: var(--bg-body-bg); + &.pie-chart { + max-height: 180px; + } + &.fullscreen { width: 100%; padding: 40px; - - .graph-legend { - top: 7rem; - left: 12rem; - } } + } - &.pie-chart { - padding-right: 0px; - padding-left: 50px; - min-height: 180px; + .graph-legend { + @include box-header-font; + margin: 0; - .graph-legend { - top: -10px; - left: 0px; + li { + display: flex; + word-wrap: break-word; + word-break: break-word; + gap: 0.5rem; + span { + flex: 1; } + div { + border: 1px solid; + margin-top: 2px; + width: 12px; + min-width: 12px; + height: 12px; - &.compact { - padding-left: 0px; - padding-top: 60px; - } - - &.legend-down { - padding-left: 0px; - padding-top: 0px; - - canvas { - margin-bottom: 25px; + &.page-views { + border-color: rgba(220,220,220,1); + background-color: rgba(220,220,220,0.2); } - - .graph-legend { - position: relative; - - li { - float: left; - width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - - &:nth-child(odd) { - margin-right: 2%; - } - } + &.unique-visitors { + border-color: rgba(151,187,205,1); + background-color: rgba(151,187,205,0.2); } - } - } - - .graph-legend { - @include box-header-font; - display: inline-block; - max-width: 100%; - position: absolute; - top: 2rem; - left: 7rem; - list-style-type: none; - padding: 0.5rem 1rem; - margin: 0; - - li { - div { - border: 1px solid; - width: 12px; - height: 12px; - vertical-align: -41%; - margin-bottom: 5px; - display: inline-block; - margin-right: 5px; - - &.page-views { - border-color: rgba(220,220,220,1); - background-color: rgba(220,220,220,0.2); - } - &.unique-visitors { - border-color: rgba(151,187,205,1); - background-color: rgba(151,187,205,0.2); - } - &.guest { - border-color: #46BFBD; - background-color: #5AD3D1; - } - &.registered { - border-color: #F7464A; - background-color: #FF5A5E; - } - &.reading-posts { - border-color: #46BFBD; - background-color: #5AD3D1; - } - &.on-categories { - border-color: #F7464A; - background-color: #FF5A5E; - } - &.browsing-topics { - border-color: #FDB45C; - background-color: #FFC870; - } - &.recent { - border-color: #949FB1; - background-color: #A8B3C5; - } - &.unread { - border-color: #949FB1; - background-color: #9FB194; - } + &.guest { + border-color: #46BFBD; + background-color: #5AD3D1; + } + &.registered { + border-color: #F7464A; + background-color: #FF5A5E; + } + &.reading-posts { + border-color: #46BFBD; + background-color: #5AD3D1; + } + &.on-categories { + border-color: #F7464A; + background-color: #FF5A5E; + } + &.browsing-topics { + border-color: #FDB45C; + background-color: #FFC870; + } + &.recent { + border-color: #949FB1; + background-color: #A8B3C5; + } + &.unread { + border-color: #949FB1; + background-color: #9FB194; } } } diff --git a/public/src/admin/advanced/errors.js b/public/src/admin/advanced/errors.js index b64f110b2a..f4d2a593c8 100644 --- a/public/src/admin/advanced/errors.js +++ b/public/src/admin/advanced/errors.js @@ -1,7 +1,9 @@ 'use strict'; -define('admin/advanced/errors', ['bootbox', 'alerts', 'Chart'], function (bootbox, alerts, Chart) { +define('admin/advanced/errors', [ + 'bootbox', 'alerts', 'chart.js/auto', +], function (bootbox, alerts, { Chart }) { const Errors = {}; Errors.init = function () { @@ -33,7 +35,7 @@ define('admin/advanced/errors', ['bootbox', 'alerts', 'Chart'], function (bootbo dailyLabels = dailyLabels.slice(-7); if (utils.isMobile()) { - Chart.defaults.global.tooltips.enabled = false; + Chart.defaults.plugins.tooltip.enabled = false; } const data = { @@ -42,6 +44,8 @@ define('admin/advanced/errors', ['bootbox', 'alerts', 'Chart'], function (bootbo datasets: [ { label: '', + fill: 'origin', + tension: 0.25, backgroundColor: 'rgba(186,139,175,0.2)', borderColor: 'rgba(186,139,175,1)', pointBackgroundColor: 'rgba(186,139,175,1)', @@ -57,6 +61,8 @@ define('admin/advanced/errors', ['bootbox', 'alerts', 'Chart'], function (bootbo datasets: [ { label: '', + fill: 'origin', + tension: 0.25, backgroundColor: 'rgba(151,187,205,0.2)', borderColor: 'rgba(151,187,205,1)', pointBackgroundColor: 'rgba(151,187,205,1)', @@ -69,23 +75,20 @@ define('admin/advanced/errors', ['bootbox', 'alerts', 'Chart'], function (bootbo }, }; - notFoundCanvas.width = $(notFoundCanvas).parent().width(); - tooBusyCanvas.width = $(tooBusyCanvas).parent().width(); - new Chart(notFoundCanvas.getContext('2d'), { type: 'line', data: data['not-found'], options: { responsive: true, - legend: { - display: false, + plugins: { + legend: { + display: false, + }, }, scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - }, - }], + y: { + beginAtZero: true, + }, }, }, }); @@ -95,15 +98,15 @@ define('admin/advanced/errors', ['bootbox', 'alerts', 'Chart'], function (bootbo data: data.toobusy, options: { responsive: true, - legend: { - display: false, + plugins: { + legend: { + display: false, + }, }, scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - }, - }], + y: { + beginAtZero: true, + }, }, }, }); diff --git a/public/src/admin/dashboard.js b/public/src/admin/dashboard.js index 3cd0b93619..2e37272813 100644 --- a/public/src/admin/dashboard.js +++ b/public/src/admin/dashboard.js @@ -2,8 +2,8 @@ define('admin/dashboard', [ - 'Chart', 'translator', 'benchpress', 'bootbox', 'alerts', 'helpers', -], function (Chart, translator, Benchpress, bootbox, alerts, helpers) { + 'chart.js/auto', 'translator', 'benchpress', 'bootbox', 'alerts', 'helpers', +], function ({ Chart }, translator, Benchpress, bootbox, alerts, helpers) { const Admin = {}; const intervals = { rooms: false, @@ -63,19 +63,19 @@ define('admin/dashboard', [ graphData.rooms = data; - const html = '
' + + const html = '
' + '' + helpers.formattedNumber(data.onlineRegisteredCount) + '' + '
[[admin/dashboard:active-users.users]]
' + '
' + - '
' + + '
' + '' + helpers.formattedNumber(data.onlineGuestCount) + '' + '
[[admin/dashboard:active-users.guests]]
' + '
' + - '
' + + '
' + '' + helpers.formattedNumber(data.onlineRegisteredCount + data.onlineGuestCount) + '' + '
[[admin/dashboard:active-users.total]]
' + '
' + - '
' + + '
' + '' + helpers.formattedNumber(data.socketCount) + '' + '
[[admin/dashboard:active-users.connections]]
' + '
'; @@ -140,7 +140,7 @@ define('admin/dashboard', [ const trafficLabels = utils.getHoursArray(); if (isMobile) { - Chart.defaults.global.tooltips.enabled = false; + Chart.defaults.plugins.tooltip.enabled = false; } const t = translator.Translator.create(); @@ -158,11 +158,14 @@ define('admin/dashboard', [ t.translateKey('admin/dashboard:recent', []), t.translateKey('admin/dashboard:unread', []), ]).then(function (translations) { + const tension = 0.25; const data = { labels: trafficLabels, datasets: [ { label: translations[0], + fill: 'origin', + tension: tension, backgroundColor: 'rgba(220,220,220,0.2)', borderColor: 'rgba(220,220,220,1)', pointBackgroundColor: 'rgba(220,220,220,1)', @@ -173,6 +176,8 @@ define('admin/dashboard', [ }, { label: translations[1], + fill: 'origin', + tension: tension, backgroundColor: '#ab464233', borderColor: '#ab4642', pointBackgroundColor: '#ab4642', @@ -183,6 +188,8 @@ define('admin/dashboard', [ }, { label: translations[2], + fill: 'origin', + tension: tension, backgroundColor: '#ba8baf33', borderColor: '#ba8baf', pointBackgroundColor: '#ba8baf', @@ -193,6 +200,8 @@ define('admin/dashboard', [ }, { label: translations[3], + fill: 'origin', + tension: tension, backgroundColor: '#f7ca8833', borderColor: '#f7ca88', pointBackgroundColor: '#f7ca88', @@ -203,6 +212,8 @@ define('admin/dashboard', [ }, { label: translations[4], + fill: 'origin', + tension: tension, backgroundColor: 'rgba(151,187,205,0.2)', borderColor: 'rgba(151,187,205,1)', pointBackgroundColor: 'rgba(151,187,205,1)', @@ -227,43 +238,42 @@ define('admin/dashboard', [ data: data, options: { responsive: true, - legend: { - display: true, - }, scales: { - yAxes: [{ - id: 'left-y-axis', - ticks: { - beginAtZero: true, - precision: 0, - }, - type: 'linear', + 'left-y-axis': { position: 'left', - scaleLabel: { - display: true, - labelString: translations[0], - }, - }, { - id: 'right-y-axis', - ticks: { - beginAtZero: true, - suggestedMax: 10, - precision: 0, - }, type: 'linear', - position: 'right', - scaleLabel: { + title: { display: true, - labelString: translations[4], + text: translations[0], }, - }], + beginAtZero: true, + }, + 'right-y-axis': { + position: 'right', + type: 'linear', + title: { + display: true, + text: translations[4], + }, + beginAtZero: true, + }, }, - tooltips: { - mode: 'x', + interaction: { + intersect: false, + mode: 'index', }, }, }); + const doughnutOpts = { + responsive: true, + maintainAspectRatio: true, + plugins: { + legend: { + display: false, + }, + }, + }; graphs.registered = new Chart(registeredCtx, { type: 'doughnut', data: { @@ -274,12 +284,7 @@ define('admin/dashboard', [ hoverBackgroundColor: ['#FF5A5E', '#5AD3D1'], }], }, - options: { - responsive: true, - legend: { - display: false, - }, - }, + options: doughnutOpts, }); graphs.presence = new Chart(presenceCtx, { @@ -292,12 +297,7 @@ define('admin/dashboard', [ hoverBackgroundColor: ['#FF5A5E', '#5AD3D1', '#FFC870', '#A8B3C5', '#A8B3C5'], }], }, - options: { - responsive: true, - legend: { - display: false, - }, - }, + options: doughnutOpts, }); graphs.topics = new Chart(topicsCtx, { @@ -310,19 +310,11 @@ define('admin/dashboard', [ hoverBackgroundColor: [], }], }, - options: { - responsive: true, - legend: { - display: false, - }, - }, + options: doughnutOpts, }); updateTrafficGraph(); - $(window).on('resize', adjustPieCharts); - adjustPieCharts(); - $('[data-action="updateGraph"]:not([data-units="custom"])').on('click', function () { let until = new Date(); const amount = $(this).attr('data-amount'); @@ -398,18 +390,6 @@ define('admin/dashboard', [ }); } - function adjustPieCharts() { - $('.pie-chart.legend-up').each(function () { - const $this = $(this); - - if ($this.width() < 320) { - $this.addClass('compact'); - } else { - $this.removeClass('compact'); - } - }); - } - function updateTrafficGraph(units, until, amount) { // until and amount are optional diff --git a/public/src/admin/manage/category-analytics.js b/public/src/admin/manage/category-analytics.js index 634f7a7e57..93c4fa0abe 100644 --- a/public/src/admin/manage/category-analytics.js +++ b/public/src/admin/manage/category-analytics.js @@ -2,8 +2,8 @@ define('admin/manage/category-analytics', [ - 'Chart', 'categorySelector', -], function (Chart, categorySelector) { + 'chart.js/auto', 'categorySelector', +], function ({ Chart }, categorySelector) { const CategoryAnalytics = {}; CategoryAnalytics.init = function () { @@ -27,20 +27,26 @@ define('admin/manage/category-analytics', [ }); if (utils.isMobile()) { - Chart.defaults.global.tooltips.enabled = false; + Chart.defaults.plugins.tooltip.enabled = false; } + const commonDataSetOpts = { + label: '', + fill: true, + tension: 0.25, + pointHoverBackgroundColor: '#fff', + pointBorderColor: '#fff', + }; + const data = { 'pageviews:hourly': { labels: hourlyLabels, datasets: [ { - label: '', + ...commonDataSetOpts, backgroundColor: 'rgba(186,139,175,0.2)', borderColor: 'rgba(186,139,175,1)', pointBackgroundColor: 'rgba(186,139,175,1)', - pointHoverBackgroundColor: '#fff', - pointBorderColor: '#fff', pointHoverBorderColor: 'rgba(186,139,175,1)', data: ajaxify.data.analytics['pageviews:hourly'], }, @@ -50,12 +56,10 @@ define('admin/manage/category-analytics', [ labels: dailyLabels, datasets: [ { - label: '', + ...commonDataSetOpts, backgroundColor: 'rgba(151,187,205,0.2)', borderColor: 'rgba(151,187,205,1)', pointBackgroundColor: 'rgba(151,187,205,1)', - pointHoverBackgroundColor: '#fff', - pointBorderColor: '#fff', pointHoverBorderColor: 'rgba(151,187,205,1)', data: ajaxify.data.analytics['pageviews:daily'], }, @@ -65,12 +69,10 @@ define('admin/manage/category-analytics', [ labels: dailyLabels.slice(-7), datasets: [ { - label: '', + ...commonDataSetOpts, backgroundColor: 'rgba(171,70,66,0.2)', borderColor: 'rgba(171,70,66,1)', pointBackgroundColor: 'rgba(171,70,66,1)', - pointHoverBackgroundColor: '#fff', - pointBorderColor: '#fff', pointHoverBorderColor: 'rgba(171,70,66,1)', data: ajaxify.data.analytics['topics:daily'], }, @@ -80,12 +82,10 @@ define('admin/manage/category-analytics', [ labels: dailyLabels.slice(-7), datasets: [ { - label: '', + ...commonDataSetOpts, backgroundColor: 'rgba(161,181,108,0.2)', borderColor: 'rgba(161,181,108,1)', pointBackgroundColor: 'rgba(161,181,108,1)', - pointHoverBackgroundColor: '#fff', - pointBorderColor: '#fff', pointHoverBorderColor: 'rgba(161,181,108,1)', data: ajaxify.data.analytics['posts:daily'], }, @@ -98,84 +98,43 @@ define('admin/manage/category-analytics', [ topicsCanvas.width = $(topicsCanvas).parent().width(); postsCanvas.width = $(postsCanvas).parent().width(); - new Chart(hourlyCanvas.getContext('2d'), { - type: 'line', - data: data['pageviews:hourly'], - options: { - responsive: true, - animation: false, + const chartOpts = { + responsive: true, + animation: false, + plugins: { legend: { display: false, }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - precision: 0, - }, - }], + }, + scales: { + y: { + beginAtZero: true, }, }, + }; + + new Chart(hourlyCanvas.getContext('2d'), { + type: 'line', + data: data['pageviews:hourly'], + options: chartOpts, }); new Chart(dailyCanvas.getContext('2d'), { type: 'line', data: data['pageviews:daily'], - options: { - responsive: true, - animation: false, - legend: { - display: false, - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - precision: 0, - }, - }], - }, - }, + options: chartOpts, }); new Chart(topicsCanvas.getContext('2d'), { type: 'line', data: data['topics:daily'], - options: { - responsive: true, - animation: false, - legend: { - display: false, - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - precision: 0, - }, - }], - }, - }, + options: chartOpts, }); new Chart(postsCanvas.getContext('2d'), { type: 'line', data: data['posts:daily'], - options: { - responsive: true, - animation: false, - legend: { - display: false, - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - precision: 0, - }, - }], - }, - }, + options: chartOpts, }); }; diff --git a/public/src/admin/modules/dashboard-line-graph.js b/public/src/admin/modules/dashboard-line-graph.js index 65ea00feaf..3a95868b6c 100644 --- a/public/src/admin/modules/dashboard-line-graph.js +++ b/public/src/admin/modules/dashboard-line-graph.js @@ -1,6 +1,8 @@ 'use strict'; -define('admin/modules/dashboard-line-graph', ['Chart', 'translator', 'benchpress', 'api', 'hooks', 'bootbox'], function (Chart, translator, Benchpress, api, hooks, bootbox) { +define('admin/modules/dashboard-line-graph', [ + 'chart.js/auto', 'translator', 'benchpress', 'api', 'hooks', 'bootbox', +], function ({ Chart }, translator, Benchpress, api, hooks, bootbox) { const Graph = { _current: null, }; @@ -13,7 +15,7 @@ define('admin/modules/dashboard-line-graph', ['Chart', 'translator', 'benchpress isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); if (isMobile) { - Chart.defaults.global.tooltips.enabled = false; + Chart.defaults.plugins.tooltip.enabled = false; } Graph.handleUpdateControls({ set }); @@ -26,6 +28,8 @@ define('admin/modules/dashboard-line-graph', ['Chart', 'translator', 'benchpress datasets: [ { label: key, + fill: true, + tension: 0.25, backgroundColor: 'rgba(151,187,205,0.2)', borderColor: 'rgba(151,187,205,1)', pointBackgroundColor: 'rgba(151,187,205,1)', @@ -46,26 +50,20 @@ define('admin/modules/dashboard-line-graph', ['Chart', 'translator', 'benchpress data: data, options: { responsive: true, - legend: { - display: true, - }, scales: { - yAxes: [{ - id: 'left-y-axis', - ticks: { - beginAtZero: true, - precision: 0, - }, + 'left-y-axis': { type: 'linear', position: 'left', - scaleLabel: { + beginAtZero: true, + title: { display: true, - labelString: key, + text: key, }, - }], + }, }, - tooltips: { - mode: 'x', + interaction: { + intersect: false, + mode: 'index', }, }, }); diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index 8c13b240e8..5c92f46292 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -1,11 +1,11 @@ 'use strict'; define('forum/flags/list', [ - 'components', 'Chart', 'categoryFilter', + 'components', 'chart.js/auto', 'categoryFilter', 'autocomplete', 'api', 'alerts', 'userFilter', ], function ( - components, Chart, categoryFilter, + components, { Chart }, categoryFilter, autocomplete, api, alerts, userFilter ) { @@ -255,7 +255,7 @@ define('forum/flags/list', [ }); if (utils.isMobile()) { - Chart.defaults.global.tooltips.enabled = false; + Chart.defaults.plugins.tooltip.enabled = false; } const data = { 'flags:daily': { @@ -282,16 +282,15 @@ define('forum/flags/list', [ options: { responsive: true, animation: false, - legend: { - display: false, + plugins: { + legend: { + display: false, + }, }, scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - precision: 0, - }, - }], + y: { + beginAtZero: true, + }, }, }, }); diff --git a/public/src/client/ip-blacklist.js b/public/src/client/ip-blacklist.js index 5fccd07a32..b94c84038a 100644 --- a/public/src/client/ip-blacklist.js +++ b/public/src/client/ip-blacklist.js @@ -1,7 +1,8 @@ 'use strict'; - -define('forum/ip-blacklist', ['Chart', 'benchpress', 'bootbox', 'alerts'], function (Chart, Benchpress, bootbox, alerts) { +define('forum/ip-blacklist', [ + 'chart.js/auto', 'benchpress', 'bootbox', 'alerts', +], function ({ Chart }, Benchpress, bootbox, alerts) { const Blacklist = {}; Blacklist.init = function () { @@ -52,7 +53,7 @@ define('forum/ip-blacklist', ['Chart', 'benchpress', 'bootbox', 'alerts'], funct }); if (utils.isMobile()) { - Chart.defaults.global.tooltips.enabled = false; + Chart.defaults.plugins.tooltip.enabled = false; } const data = { @@ -61,6 +62,8 @@ define('forum/ip-blacklist', ['Chart', 'benchpress', 'bootbox', 'alerts'], funct datasets: [ { label: '', + fill: 'origin', + tension: 0.25, backgroundColor: 'rgba(186,139,175,0.2)', borderColor: 'rgba(186,139,175,1)', pointBackgroundColor: 'rgba(186,139,175,1)', @@ -88,45 +91,34 @@ define('forum/ip-blacklist', ['Chart', 'benchpress', 'bootbox', 'alerts'], funct }, }; - hourlyCanvas.width = $(hourlyCanvas).parent().width(); - dailyCanvas.width = $(dailyCanvas).parent().width(); + const chartOpts = { + responsive: true, + maintainAspectRatio: true, + plugins: { + legend: { + display: false, + }, + }, + scales: { + y: { + position: 'left', + type: 'linear', + beginAtZero: true, + }, + }, + }; + new Chart(hourlyCanvas.getContext('2d'), { type: 'line', data: data['blacklist:hourly'], - options: { - responsive: true, - animation: false, - legend: { - display: false, - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - }, - }], - }, - }, + options: chartOpts, }); new Chart(dailyCanvas.getContext('2d'), { type: 'line', data: data['blacklist:daily'], - options: { - responsive: true, - animation: false, - legend: { - display: false, - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - }, - }], - }, - }, + options: chartOpts, }); }; diff --git a/src/views/admin/advanced/errors.tpl b/src/views/admin/advanced/errors.tpl index 398115c9ff..d5baa12a82 100644 --- a/src/views/admin/advanced/errors.tpl +++ b/src/views/admin/advanced/errors.tpl @@ -17,8 +17,10 @@
-
-
+
+
+ +