dashboard next: trending search report
This commit also improves how data is loaded sync and async
This commit is contained in:
+1
-1
@@ -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-mini-table"],
|
||||
classNames: ["dashboard-table", "dashboard-inline-table"],
|
||||
|
||||
classNameBindings: ["isLoading"],
|
||||
|
||||
@@ -11,22 +11,18 @@ export default Ember.Component.extend({
|
||||
total: null,
|
||||
trend: null,
|
||||
title: null,
|
||||
chartData: null,
|
||||
oneDataPoint: false,
|
||||
backgroundColor: "rgba(200,220,240,0.3)",
|
||||
borderColor: "#08C",
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
this._initializeChart();
|
||||
},
|
||||
|
||||
didUpdateAttrs() {
|
||||
this._super();
|
||||
|
||||
loadScript("/javascripts/Chart.min.js").then(() => {
|
||||
if (this.get("model") && !this.get("chartData")) {
|
||||
this._setPropertiesFromModel(this.get("model"));
|
||||
this._drawChart();
|
||||
} else if (this.get("dataSource")) {
|
||||
this._fetchReport();
|
||||
}
|
||||
});
|
||||
this._initializeChart();
|
||||
},
|
||||
|
||||
@computed("dataSourceName")
|
||||
@@ -75,13 +71,27 @@ 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 context = this.$(".chart-canvas")[0].getContext("2d");
|
||||
const $chartCanvas = this.$(".chart-canvas");
|
||||
if (!$chartCanvas.length) return;
|
||||
|
||||
const context = $chartCanvas[0].getContext("2d");
|
||||
|
||||
const data = {
|
||||
labels: this.get("chartData").map(r => r.x),
|
||||
labels: this.get("labels"),
|
||||
datasets: [{
|
||||
data: this.get("chartData").map(r => r.y),
|
||||
data: this.get("values"),
|
||||
backgroundColor: this.get("backgroundColor"),
|
||||
borderColor: this.get("borderColor")
|
||||
}]
|
||||
@@ -92,17 +102,18 @@ export default Ember.Component.extend({
|
||||
|
||||
_setPropertiesFromModel(model) {
|
||||
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),
|
||||
chartData: model.data
|
||||
trend: this._computeTrend(model.total, model.prev30Days)
|
||||
});
|
||||
},
|
||||
|
||||
_buildChartConfig(data) {
|
||||
const values = this.get("chartData").map(d => d.y);
|
||||
const values = this.get("values");
|
||||
const max = Math.max(...values);
|
||||
const min = Math.min(...values);
|
||||
const stepSize = Math.max(...[Math.ceil((max - min)/5), 20]);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import DashboardTable from "admin/components/dashboard-table";
|
||||
import { number } from 'discourse/lib/formatter';
|
||||
|
||||
export default DashboardTable.extend({
|
||||
layoutName: "admin/templates/components/dashboard-table",
|
||||
|
||||
classNames: ["dashboard-table", "dashboard-table-trending-search"],
|
||||
|
||||
transformModel(model) {
|
||||
return {
|
||||
labels: model.labels,
|
||||
values: model.data.map(data => {
|
||||
return [data[0], number(data[1]), number(data[2])];
|
||||
})
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["dashboard-table"],
|
||||
|
||||
classNameBindings: ["isLoading"],
|
||||
|
||||
total: null,
|
||||
labels: null,
|
||||
title: null,
|
||||
chartData: null,
|
||||
isLoading: false,
|
||||
help: null,
|
||||
helpPage: null,
|
||||
model: null,
|
||||
|
||||
transformModel(model) {
|
||||
const data = model.data.sort((a, b) => a.x >= b.x);
|
||||
|
||||
return {
|
||||
labels: model.labels,
|
||||
values: data
|
||||
};
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
this._initializeTable();
|
||||
},
|
||||
|
||||
didUpdateAttrs() {
|
||||
this._super();
|
||||
this._initializeTable();
|
||||
},
|
||||
|
||||
@computed("dataSourceName")
|
||||
dataSource(dataSourceName) {
|
||||
return `/admin/reports/${dataSourceName}`;
|
||||
},
|
||||
|
||||
_initializeTable() {
|
||||
if (this.get("model") && !this.get("values")) {
|
||||
this._setPropertiesFromModel(this.get("model"));
|
||||
} else if (this.get("dataSource")) {
|
||||
this._fetchReport();
|
||||
}
|
||||
},
|
||||
|
||||
_fetchReport() {
|
||||
if (this.get("isLoading")) return;
|
||||
|
||||
this.set("isLoading", true);
|
||||
|
||||
let payload = {data: {}};
|
||||
|
||||
if (this.get("startDate")) {
|
||||
payload.data.start_date = this.get("startDate").toISOString();
|
||||
}
|
||||
|
||||
if (this.get("endDate")) {
|
||||
payload.data.end_date = this.get("endDate").toISOString();
|
||||
}
|
||||
|
||||
ajax(this.get("dataSource"), payload)
|
||||
.then((response) => {
|
||||
this._setPropertiesFromModel(response.report);
|
||||
}).finally(() => {
|
||||
this.set("isLoading", false);
|
||||
});
|
||||
},
|
||||
|
||||
_setPropertiesFromModel(model) {
|
||||
const { labels, values } = this.transformModel(model);
|
||||
|
||||
this.setProperties({
|
||||
labels,
|
||||
values,
|
||||
total: model.total,
|
||||
title: model.title
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -34,7 +34,7 @@ export default Ember.Controller.extend({
|
||||
}).finally(() => {
|
||||
this.set("isLoading", false);
|
||||
});
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@computed("period")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export default Discourse.Route.extend({
|
||||
setupController(controller) {
|
||||
controller.fetchDashboard();
|
||||
activate() {
|
||||
this.controllerFor('admin-dashboard-next').fetchDashboard();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{{#conditional-loading-spinner condition=isLoading}}
|
||||
<div class="table-title">
|
||||
<h3>{{title}}</h3>
|
||||
|
||||
{{#if help}}
|
||||
<a href="{{helpPage}}">{{i18n help}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{{#each labels as |label|}}
|
||||
<th>{{label}}</th>
|
||||
{{/each}}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{#each values as |value|}}
|
||||
<tr>
|
||||
{{#each value as |v|}}
|
||||
<td>{{v}}</td>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{/conditional-loading-spinner}}
|
||||
@@ -1,72 +1,82 @@
|
||||
{{plugin-outlet name="admin-dashboard-top"}}
|
||||
|
||||
|
||||
<div class="community-health section">
|
||||
<div class="section-title">
|
||||
<h2>{{i18n "admin.dashboard.community_health"}}</h2>
|
||||
{{period-chooser period=period action="changePeriod"}}
|
||||
</div>
|
||||
|
||||
<div class="section-body">
|
||||
<div class="charts">
|
||||
{{dashboard-mini-chart
|
||||
model=global_reports_signups
|
||||
dataSourceName="signups"
|
||||
startDate=startDate
|
||||
endDate=endDate
|
||||
help="admin.dashboard.charts.signups.help"}}
|
||||
|
||||
{{dashboard-mini-chart
|
||||
model=global_reports_topics
|
||||
dataSourceName="topics"
|
||||
startDate=startDate
|
||||
endDate=endDate
|
||||
help="admin.dashboard.charts.topics.help"}}
|
||||
</div>
|
||||
</div>
|
||||
{{lastRefreshedAt}}
|
||||
<div class="community-health section">
|
||||
<div class="section-title">
|
||||
<h2>{{i18n "admin.dashboard.community_health"}}</h2>
|
||||
{{period-chooser period=period action="changePeriod"}}
|
||||
</div>
|
||||
|
||||
<div class="section-columns">
|
||||
<div class="section-column">
|
||||
{{dashboard-mini-table model=user_reports_users_by_type isLoading=isLoading}}
|
||||
{{dashboard-mini-table model=user_reports_users_by_trust_level isLoading=isLoading}}
|
||||
<div class="section-body">
|
||||
<div class="charts">
|
||||
{{dashboard-mini-chart
|
||||
model=global_reports_signups
|
||||
dataSourceName="signups"
|
||||
startDate=startDate
|
||||
endDate=endDate
|
||||
help="admin.dashboard.charts.signups.help"}}
|
||||
|
||||
{{#conditional-loading-spinner isLoading=isLoading}}
|
||||
<div class="misc">
|
||||
<div class="durability">
|
||||
{{#if currentUser.admin}}
|
||||
<div class="backups">
|
||||
<h3 class="durability-title"><a href="/admin/backups">{{i18n "admin.dashboard.backups"}}</a></h3>
|
||||
<p>
|
||||
{{disk_space.backups_used}} ({{i18n "admin.dashboard.space_free" size=disk_space.backups_free}})
|
||||
<br />
|
||||
{{{i18n "admin.dashboard.lastest_backup" date=backupTimestamp}}}
|
||||
</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{dashboard-mini-chart
|
||||
model=global_reports_topics
|
||||
dataSourceName="topics"
|
||||
startDate=startDate
|
||||
endDate=endDate
|
||||
help="admin.dashboard.charts.topics.help"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uploads">
|
||||
<h3 class="durability-title">{{i18n "admin.dashboard.uploads"}}</h3>
|
||||
<div class="section-columns">
|
||||
<div class="section-column">
|
||||
{{dashboard-inline-table
|
||||
model=user_reports_users_by_type
|
||||
lastRefreshedAt=lastRefreshedAt
|
||||
isLoading=isLoading}}
|
||||
|
||||
{{dashboard-inline-table
|
||||
model=user_reports_users_by_trust_level
|
||||
lastRefreshedAt=lastRefreshedAt
|
||||
isLoading=isLoading}}
|
||||
|
||||
{{#conditional-loading-spinner isLoading=isLoading}}
|
||||
<div class="misc">
|
||||
<div class="durability">
|
||||
{{#if currentUser.admin}}
|
||||
<div class="backups">
|
||||
<h3 class="durability-title"><a href="/admin/backups">{{i18n "admin.dashboard.backups"}}</a></h3>
|
||||
<p>
|
||||
{{disk_space.uploads_used}} ({{i18n "admin.dashboard.space_free" size=disk_space.uploads_free}})
|
||||
{{disk_space.backups_used}} ({{i18n "admin.dashboard.space_free" size=disk_space.backups_free}})
|
||||
<br />
|
||||
{{{i18n "admin.dashboard.lastest_backup" date=backupTimestamp}}}
|
||||
</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="uploads">
|
||||
<h3 class="durability-title">{{i18n "admin.dashboard.uploads"}}</h3>
|
||||
<p>
|
||||
{{disk_space.uploads_used}} ({{i18n "admin.dashboard.space_free" size=disk_space.uploads_free}})
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<p class="last-dashboard-update">
|
||||
{{i18n "admin.dashboard.last_updated"}} {{updatedTimestamp}}
|
||||
</p>
|
||||
|
||||
<a rel="noopener" target="_blank" href="https://meta.discourse.org/t/discourse-2-0-0-beta6-release-notes/85241" class="btn">
|
||||
{{i18n "admin.dashboard.whats_new_in_discourse"}}
|
||||
</a>
|
||||
</div>
|
||||
{{/conditional-loading-spinner}}
|
||||
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div class="section-column">
|
||||
</div>
|
||||
<p class="last-dashboard-update">
|
||||
{{i18n "admin.dashboard.last_updated"}} {{updatedTimestamp}}
|
||||
</p>
|
||||
|
||||
<a rel="noopener" target="_blank" href="https://meta.discourse.org/t/discourse-2-0-0-beta6-release-notes/85241" class="btn">
|
||||
{{i18n "admin.dashboard.whats_new_in_discourse"}}
|
||||
</a>
|
||||
</div>
|
||||
{{/conditional-loading-spinner}}
|
||||
</div>
|
||||
|
||||
<div class="section-column">
|
||||
{{dashboard-table-trending-search
|
||||
model=global_reports_trending_search
|
||||
dataSourceName="trending_search"
|
||||
startDate=startDate
|
||||
endDate=endDate}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user