diff --git a/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6 b/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6 index 070625e9e47..dd8582461bf 100644 --- a/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6 +++ b/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6 @@ -2,7 +2,7 @@ import { ajax } from 'discourse/lib/ajax'; import computed from 'ember-addons/ember-computed-decorators'; export default Ember.Component.extend({ - classNames: ["dashboard-table", "dashboard-inline-table"], + classNames: ["dashboard-table", "dashboard-inline-table", "fixed"], classNameBindings: ["isLoading"], diff --git a/app/assets/javascripts/admin/components/dashboard-mini-chart.js.es6 b/app/assets/javascripts/admin/components/dashboard-mini-chart.js.es6 index eea4bc917cd..3b56917f997 100644 --- a/app/assets/javascripts/admin/components/dashboard-mini-chart.js.es6 +++ b/app/assets/javascripts/admin/components/dashboard-mini-chart.js.es6 @@ -1,6 +1,7 @@ -import { ajax } from 'discourse/lib/ajax'; -import computed from 'ember-addons/ember-computed-decorators'; -import loadScript from 'discourse/lib/load-script'; +import { ajax } from "discourse/lib/ajax"; +import computed from "ember-addons/ember-computed-decorators"; +import loadScript from "discourse/lib/load-script"; +import Report from "admin/models/report"; export default Ember.Component.extend({ classNames: ["dashboard-mini-chart"], @@ -17,12 +18,26 @@ export default Ember.Component.extend({ didInsertElement() { this._super(); - this._initializeChart(); + + if (this.get("model")) { + loadScript("/javascripts/Chart.min.js").then(() => { + this._setPropertiesFromModel(this.get("model")); + this._drawChart(); + }); + } }, didUpdateAttrs() { this._super(); - this._initializeChart(); + + loadScript("/javascripts/Chart.min.js").then(() => { + if (this.get("model") && !this.get("values")) { + this._setPropertiesFromModel(this.get("model")); + this._drawChart(); + } else if (this.get("dataSource")) { + this._fetchReport(); + } + }); }, @computed("dataSourceName") @@ -34,10 +49,17 @@ export default Ember.Component.extend({ @computed("trend") trendIcon(trend) { - if (trend === "stable") { - return null; - } else { - return `angle-${trend}`; + switch (trend) { + case "trending-up": + return "angle-up"; + case "trending-down": + return "angle-down"; + case "high-trending-up": + return "angle-double-up"; + case "high-trending-down": + return "angle-double-down"; + default: + return null; } }, @@ -46,7 +68,9 @@ export default Ember.Component.extend({ this.set("isLoading", true); - let payload = {data: {}}; + let payload = { + data: {} + }; if (this.get("startDate")) { payload.data.start_date = this.get("startDate").toISOString(); @@ -58,7 +82,7 @@ export default Ember.Component.extend({ ajax(this.get("dataSource"), payload) .then((response) => { - this._setPropertiesFromModel(response.report); + this._setPropertiesFromModel(Report.create(response.report)); }) .finally(() => { this.set("isLoading", false); @@ -71,17 +95,6 @@ export default Ember.Component.extend({ }); }, - _initializeChart() { - loadScript("/javascripts/Chart.min.js").then(() => { - if (this.get("model") && !this.get("values")) { - this._setPropertiesFromModel(this.get("model")); - this._drawChart(); - } else if (this.get("dataSource")) { - this._fetchReport(); - } - }); - }, - _drawChart() { const $chartCanvas = this.$(".chart-canvas"); if (!$chartCanvas.length) return; @@ -91,7 +104,7 @@ export default Ember.Component.extend({ const data = { labels: this.get("labels"), datasets: [{ - data: this.get("values"), + data: Ember.makeArray(this.get("values")), backgroundColor: this.get("backgroundColor"), borderColor: this.get("borderColor") }] @@ -100,72 +113,64 @@ export default Ember.Component.extend({ this._chart = new window.Chart(context, this._buildChartConfig(data)); }, - _setPropertiesFromModel(model) { + _setPropertiesFromModel(report) { + const oneDataPoint = (this.get("startDate") && this.get("endDate")) && + this.get("startDate").isSame(this.get("endDate"), "day"); + this.setProperties({ - labels: model.data.map(r => r.x), - values: model.data.map(r => r.y), - oneDataPoint: (this.get("startDate") && this.get("endDate")) && - this.get("startDate").isSame(this.get("endDate"), 'day'), - total: model.total, - title: model.title, - trend: this._computeTrend(model.total, model.prev30Days) + oneDataPoint, + labels: report.get("data").map(r => r.x), + values: report.get("data").map(r => r.y), + total: report.get("total"), + description: report.get("description"), + title: report.get("title"), + trend: report.get("sevenDayTrend"), + prev30Days: report.get("prev30Days"), }); }, _buildChartConfig(data) { - const values = this.get("values"); + const values = data.datasets[0].data; const max = Math.max(...values); const min = Math.min(...values); - const stepSize = Math.max(...[Math.ceil((max - min)/5), 20]); - const startDate = this.get("startDate") || moment(); - const endDate = this.get("endDate") || moment(); - const datesDifference = startDate.diff(endDate, "days"); - let unit = "day"; - if (datesDifference >= 366) { - unit = "quarter"; - } else if (datesDifference >= 61) { - unit = "month"; - } else if (datesDifference >= 14) { - unit = "week"; - } + const stepSize = Math.max(...[Math.ceil((max - min) / 5) * 5, 20]); return { type: "line", data, options: { - legend: { display: false }, + legend: { + display: false + }, responsive: true, - layout: { padding: { left: 0, top: 0, right: 0, bottom: 0 } }, + maintainAspectRatio: false, + layout: { + padding: { + left: 0, + top: 0, + right: 0, + bottom: 0 + } + }, scales: { - yAxes: [ - { - display: true, - ticks: { suggestedMin: 0, stepSize, suggestedMax: max + stepSize } + yAxes: [{ + display: true, + ticks: { + suggestedMin: 0, + stepSize, + suggestedMax: max + stepSize } - ], - xAxes: [ - { - display: true, - type: "time", - time: { - parser: "YYYY-MM-DD", - unit - } + }], + xAxes: [{ + display: true, + type: "time", + time: { + parser: "YYYY-MM-DD" } - ], + }], } }, }; - }, - - _computeTrend(total, prevTotal) { - const percentChange = ((total - prevTotal) / prevTotal) * 100; - - if (percentChange > 50) return "double-up"; - if (percentChange > 0) return "up"; - if (percentChange === 0) return "stable"; - if (percentChange < 50) return "double-down"; - if (percentChange < 0) return "down"; - }, + } }); diff --git a/app/assets/javascripts/admin/controllers/admin-dashboard-next.js.es6 b/app/assets/javascripts/admin/controllers/admin-dashboard-next.js.es6 index 3afb55343dd..0c56cfe971a 100644 --- a/app/assets/javascripts/admin/controllers/admin-dashboard-next.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-dashboard-next.js.es6 @@ -1,11 +1,6 @@ import DiscourseURL from "discourse/lib/url"; import computed from "ember-addons/ember-computed-decorators"; import AdminDashboardNext from 'admin/models/admin-dashboard-next'; -import Report from 'admin/models/report'; - -const ATTRIBUTES = [ "disk_space", "updated_at", "last_backup_taken_at"]; - -const REPORTS = [ "global_reports", "user_reports" ]; export default Ember.Controller.extend({ queryParams: ["period"], @@ -14,20 +9,17 @@ export default Ember.Controller.extend({ dashboardFetchedAt: null, exceptionController: Ember.inject.controller('exception'), + diskSpace: Ember.computed.alias("model.attributes.disk_space"), + fetchDashboard() { if (this.get("isLoading")) return; if (!this.get("dashboardFetchedAt") || moment().subtract(30, "minutes").toDate() > this.get("dashboardFetchedAt")) { this.set("isLoading", true); - AdminDashboardNext.find().then(d => { + AdminDashboardNext.find().then(adminDashboardNextModel => { this.set("dashboardFetchedAt", new Date()); - - const reports = {}; - REPORTS.forEach(name => d[name].forEach(r => reports[`${name}_${r.type}`] = Report.create(r))); - this.setProperties(reports); - - ATTRIBUTES.forEach(a => this.set(a, d[a])); + this.set("model", adminDashboardNextModel); }).catch(e => { this.get("exceptionController").set("thrown", e.jqXHR); this.replaceRoute("exception"); diff --git a/app/assets/javascripts/admin/models/admin-dashboard-next.js.es6 b/app/assets/javascripts/admin/models/admin-dashboard-next.js.es6 index fb4d7519c30..880c2d5488f 100644 --- a/app/assets/javascripts/admin/models/admin-dashboard-next.js.es6 +++ b/app/assets/javascripts/admin/models/admin-dashboard-next.js.es6 @@ -1,9 +1,13 @@ -import { ajax } from 'discourse/lib/ajax'; +import { ajax } from "discourse/lib/ajax"; +import Report from "admin/models/report"; + +const ATTRIBUTES = [ "disk_space", "updated_at", "last_backup_taken_at"]; + +const REPORTS = [ "global_reports", "user_reports" ]; const AdminDashboardNext = Discourse.Model.extend({}); AdminDashboardNext.reopenClass({ - /** Fetch all dashboard data. This can be an expensive request when the cached data has expired and the server must collect the data again. @@ -11,13 +15,26 @@ AdminDashboardNext.reopenClass({ @method find @return {jqXHR} a jQuery Promise object **/ - find: function() { + find() { return ajax("/admin/dashboard-next.json").then(function(json) { - var model = AdminDashboardNext.create(json); - model.set('loaded', true); + var model = AdminDashboardNext.create(); + + const reports = {}; + REPORTS.forEach(name => json[name].forEach(r => { + if (!reports[name]) reports[name] = {}; + reports[name][r.type] = Report.create(r); + })); + model.set("reports", reports); + + const attributes = {}; + ATTRIBUTES.forEach(a => attributes[a] = json[a]); + model.set("attributes", attributes); + + model.set("loaded", true); + return model; }); - }, + } }); export default AdminDashboardNext; diff --git a/app/assets/javascripts/admin/models/report.js.es6 b/app/assets/javascripts/admin/models/report.js.es6 index 3ed442bb0d2..fac048a62a4 100644 --- a/app/assets/javascripts/admin/models/report.js.es6 +++ b/app/assets/javascripts/admin/models/report.js.es6 @@ -60,12 +60,18 @@ const Report = Discourse.Model.extend({ sevenDayTrend() { const currentPeriod = this.valueFor(1, 7); const prevPeriod = this.valueFor(8, 14); - if (currentPeriod > prevPeriod) { + const change = ((currentPeriod - prevPeriod) / prevPeriod) * 100; + + if (change > 50) { + return "high-trending-up"; + } else if (change > 0) { return "trending-up"; - } else if (currentPeriod < prevPeriod) { - return "trending-down"; - } else { + } else if (change === 0) { return "no-change"; + } else if (change < -50) { + return "high-trending-down"; + } else if (change < 0) { + return "trending-down"; } }, diff --git a/app/assets/javascripts/admin/templates/components/dashboard-mini-chart.hbs b/app/assets/javascripts/admin/templates/components/dashboard-mini-chart.hbs index 7f12611bc98..20fb90063d6 100644 --- a/app/assets/javascripts/admin/templates/components/dashboard-mini-chart.hbs +++ b/app/assets/javascripts/admin/templates/components/dashboard-mini-chart.hbs @@ -2,8 +2,10 @@
+ | {{i18n 'admin.dashboard.reports.today'}} | +{{i18n 'admin.dashboard.reports.yesterday'}} | +{{i18n 'admin.dashboard.reports.last_7_days'}} | +{{i18n 'admin.dashboard.reports.last_30_days'}} | +{{i18n 'admin.dashboard.reports.all'}} | +
---|
- {{disk_space.backups_used}} ({{i18n "admin.dashboard.space_free" size=disk_space.backups_free}})
+ {{diskSpace.backups_used}} ({{i18n "admin.dashboard.space_free" size=diskSpace.backups_free}})
{{{i18n "admin.dashboard.lastest_backup" date=backupTimestamp}}}
- {{disk_space.uploads_used}} ({{i18n "admin.dashboard.space_free" size=disk_space.uploads_free}}) + {{diskSpace.uploads_used}} ({{i18n "admin.dashboard.space_free" size=diskSpace.uploads_free}})