UX: refactoring/refining tables of new dashboard
This commit is contained in:
parent
7285e7fbba
commit
508b65b76a
|
@ -1,32 +1,13 @@
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
import Report from "admin/models/report";
|
||||
import AsyncReport from "admin/mixins/async-report";
|
||||
|
||||
export default Ember.Component.extend(AsyncReport, {
|
||||
classNames: ["dashboard-table", "dashboard-inline-table", "fixed"],
|
||||
help: null,
|
||||
helpPage: null,
|
||||
|
||||
loadReport(report_json) {
|
||||
return Report.create(report_json);
|
||||
},
|
||||
classNames: ["dashboard-inline-table"],
|
||||
|
||||
fetchReport() {
|
||||
this._super();
|
||||
|
||||
let payload = { data: { cache: true, facets: ["total", "prev30Days"] } };
|
||||
|
||||
if (this.get("startDate")) {
|
||||
payload.data.start_date = this.get("startDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
|
||||
}
|
||||
|
||||
if (this.get("endDate")) {
|
||||
payload.data.end_date = this.get("endDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
|
||||
}
|
||||
|
||||
if (this.get("limit")) {
|
||||
payload.data.limit = this.get("limit");
|
||||
}
|
||||
let payload = this.buildPayload(["total", "prev30Days"]);
|
||||
|
||||
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => {
|
||||
return ajax(dataSource, payload)
|
||||
|
|
|
@ -52,17 +52,7 @@ export default Ember.Component.extend(AsyncReport, {
|
|||
fetchReport() {
|
||||
this._super();
|
||||
|
||||
let payload = {
|
||||
data: { cache: true, facets: ["prev_period"] }
|
||||
};
|
||||
|
||||
if (this.get("startDate")) {
|
||||
payload.data.start_date = this.get("startDate").locale('en').format('YYYY-MM-DD[T]HH:mm:ss.SSSZZ');
|
||||
}
|
||||
|
||||
if (this.get("endDate")) {
|
||||
payload.data.end_date = this.get("endDate").locale('en').format('YYYY-MM-DD[T]HH:mm:ss.SSSZZ');
|
||||
}
|
||||
let payload = this.buildPayload(["prev_period"]);
|
||||
|
||||
if (this._chart) {
|
||||
this._chart.destroy();
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
import AsyncReport from "admin/mixins/async-report";
|
||||
|
||||
export default Ember.Component.extend(AsyncReport, {
|
||||
classNames: ["dashboard-table"],
|
||||
|
||||
fetchReport() {
|
||||
this._super();
|
||||
|
||||
let payload = this.buildPayload(["total", "prev30Days"]);
|
||||
|
||||
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => {
|
||||
return ajax(dataSource, payload)
|
||||
.then(response => {
|
||||
this.get("reports").pushObject(this.loadReport(response.report));
|
||||
});
|
||||
}));
|
||||
}
|
||||
});
|
|
@ -1,4 +1,5 @@
|
|||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import Report from "admin/models/report";
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
classNameBindings: ["isLoading", "dataSourceNames"],
|
||||
|
@ -17,6 +18,24 @@ export default Ember.Mixin.create({
|
|||
return dataSourceNames.split(",").map(source => `/admin/reports/${source}`);
|
||||
},
|
||||
|
||||
buildPayload(facets) {
|
||||
let payload = { data: { cache: true, facets } };
|
||||
|
||||
if (this.get("startDate")) {
|
||||
payload.data.start_date = this.get("startDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
|
||||
}
|
||||
|
||||
if (this.get("endDate")) {
|
||||
payload.data.end_date = this.get("endDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
|
||||
}
|
||||
|
||||
if (this.get("limit")) {
|
||||
payload.data.limit = this.get("limit");
|
||||
}
|
||||
|
||||
return payload;
|
||||
},
|
||||
|
||||
@computed("reports.[]", "startDate", "endDate", "dataSourceNames")
|
||||
reportsForPeriod(reports, startDate, endDate, dataSourceNames) {
|
||||
// on a slow network fetchReport could be called multiple times between
|
||||
|
@ -69,7 +88,9 @@ export default Ember.Mixin.create({
|
|||
this.set("isLoading", false);
|
||||
},
|
||||
|
||||
loadReport() {},
|
||||
loadReport(jsonReport) {
|
||||
return Report.create(jsonReport);
|
||||
},
|
||||
|
||||
fetchReport() {
|
||||
this.set("reports", []);
|
||||
|
|
|
@ -1,40 +1,31 @@
|
|||
{{#conditional-loading-section isLoading=isLoading}}
|
||||
<div class="table-title">
|
||||
<h3>{{title}}</h3>
|
||||
|
||||
{{#if help}}
|
||||
<a href="{{helpPage}}">{{i18n help}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#each reportsForPeriod as |report|}}
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{{#if report.labels}}
|
||||
{{#each report.labels as |label|}}
|
||||
<th>{{label}}</th>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{#each report.data as |data|}}
|
||||
<th>{{data.x}}</th>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#unless hasBlock}}
|
||||
{{#each report.data as |data|}}
|
||||
<tr>
|
||||
<td>{{number data.y}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{yield (hash report=report)}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{#unless hasBlock}}
|
||||
{{#each report.data as |data|}}
|
||||
<div class="table-cell">
|
||||
<span class="label">
|
||||
{{#if data.icon}}
|
||||
{{d-icon data.icon}}
|
||||
{{/if}}
|
||||
{{data.x}}:
|
||||
</span>
|
||||
<span class="value">
|
||||
{{#if data.url}}
|
||||
<a href="{{data.url}}">{{number data.y}}</a>
|
||||
{{else}}
|
||||
{{number data.y}}
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{yield (hash report=report)}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{/each}}
|
||||
{{/conditional-loading-section}}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
{{#conditional-loading-section isLoading=isLoading}}
|
||||
<div class="table-title">
|
||||
<h3>{{title}}</h3>
|
||||
</div>
|
||||
|
||||
{{#each reportsForPeriod as |report|}}
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{{#if report.labels}}
|
||||
{{#each report.labels as |label|}}
|
||||
<th>{{label}}</th>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{#each report.data as |data|}}
|
||||
<th>{{data.x}}</th>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#unless hasBlock}}
|
||||
{{#each report.data as |data|}}
|
||||
<tr>
|
||||
<td>{{number data.y}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{yield (hash report=report)}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{/each}}
|
||||
{{/conditional-loading-section}}
|
|
@ -80,17 +80,9 @@
|
|||
{{/conditional-loading-section}}
|
||||
</div>
|
||||
|
||||
{{#dashboard-inline-table dataSourceNames="users_by_type,users_by_trust_level" lastRefreshedAt=lastRefreshedAt as |context|}}
|
||||
<tr>
|
||||
{{#each context.report.data as |data|}}
|
||||
<td>
|
||||
<a href="/admin/users/list/{{data.key}}">
|
||||
{{number data.y}}
|
||||
</a>
|
||||
</td>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{/dashboard-inline-table}}
|
||||
{{dashboard-inline-table dataSourceNames="users_by_type" lastRefreshedAt=lastRefreshedAt}}
|
||||
|
||||
{{dashboard-inline-table dataSourceNames="users_by_trust_level" lastRefreshedAt=lastRefreshedAt}}
|
||||
|
||||
{{#conditional-loading-section isLoading=isLoading title=(i18n "admin.dashboard.backups")}}
|
||||
<div class="misc">
|
||||
|
@ -116,7 +108,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="last-dashboard-update">
|
||||
<div>
|
||||
<h4>{{i18n "admin.dashboard.last_updated"}} </h4>
|
||||
|
@ -128,58 +119,57 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
{{i18n 'admin.dashboard.find_old'}} {{#link-to 'admin.dashboard'}}{{i18n "admin.dashboard.old_link"}}{{/link-to}}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{{i18n 'admin.dashboard.find_old'}} {{#link-to 'admin.dashboard'}}{{i18n "admin.dashboard.old_link"}}{{/link-to}}
|
||||
</p>
|
||||
{{/conditional-loading-section}}
|
||||
</div>
|
||||
|
||||
<div class="section-column">
|
||||
<div class="top-referred-topics">
|
||||
{{#dashboard-inline-table
|
||||
dataSourceNames="top_referred_topics"
|
||||
lastRefreshedAt=lastRefreshedAt
|
||||
limit=8
|
||||
as |context|}}
|
||||
{{#each context.report.data as |data|}}
|
||||
<tr>
|
||||
<td class='left'>
|
||||
<a href="{{data.topic_url}}">
|
||||
{{data.topic_title}}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{data.num_clicks}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/dashboard-inline-table}}
|
||||
{{#dashboard-table
|
||||
dataSourceNames="top_referred_topics"
|
||||
lastRefreshedAt=lastRefreshedAt
|
||||
limit=8
|
||||
as |context|}}
|
||||
{{#each context.report.data as |data|}}
|
||||
<tr>
|
||||
<td class='left'>
|
||||
<a href="{{data.topic_url}}">
|
||||
{{data.topic_title}}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{data.num_clicks}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/dashboard-table}}
|
||||
</div>
|
||||
|
||||
<div class="trending-search">
|
||||
{{#dashboard-inline-table
|
||||
limit=8
|
||||
dataSourceNames="trending_search"
|
||||
isEnabled=logSearchQueriesEnabled
|
||||
disabledLabel="admin.dashboard.reports.trending_search.disabled"
|
||||
startDate=lastWeek
|
||||
endDate=endDate as |context|}}
|
||||
{{#each context.report.data as |data|}}
|
||||
<tr>
|
||||
<td class='left'>
|
||||
{{data.term}}
|
||||
</td>
|
||||
<td>
|
||||
{{number data.unique_searches}}
|
||||
</td>
|
||||
<td>
|
||||
{{data.ctr}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/dashboard-inline-table}}
|
||||
{{#dashboard-table
|
||||
limit=8
|
||||
dataSourceNames="trending_search"
|
||||
isEnabled=logSearchQueriesEnabled
|
||||
disabledLabel="admin.dashboard.reports.trending_search.disabled"
|
||||
startDate=lastWeek
|
||||
endDate=endDate as |context|}}
|
||||
{{#each context.report.data as |data|}}
|
||||
<tr>
|
||||
<td class='left'>
|
||||
{{data.term}}
|
||||
</td>
|
||||
<td>
|
||||
{{number data.unique_searches}}
|
||||
</td>
|
||||
<td>
|
||||
{{data.ctr}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/dashboard-table}}
|
||||
{{{i18n "admin.dashboard.reports.trending_search.more"}}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -370,6 +370,32 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dashboard-inline-table {
|
||||
margin-bottom: 1em;
|
||||
|
||||
.table-title {
|
||||
border-bottom: 1px solid $primary-low;
|
||||
margin-bottom: 1em;
|
||||
padding-bottom: .5em;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.table-cell {
|
||||
margin-right: .5em;
|
||||
display: flex;
|
||||
|
||||
.label {
|
||||
font-weight: 700;
|
||||
margin-right: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-table.activity-metrics {
|
||||
table {
|
||||
@media screen and (min-width: 400px) {
|
||||
|
@ -381,7 +407,7 @@
|
|||
.d-icon {
|
||||
color: $primary-low-mid;
|
||||
min-width: 14px;
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
@media screen and (max-width: 400px) {
|
||||
.d-icon { display: none; }
|
||||
|
|
|
@ -341,8 +341,11 @@ class Report
|
|||
|
||||
def self.report_users_by_trust_level(report)
|
||||
report.data = []
|
||||
|
||||
User.real.group('trust_level').count.sort.each do |level, count|
|
||||
report.data << { key: TrustLevel.levels[level.to_i], x: level.to_i, y: count }
|
||||
key = TrustLevel.levels[level.to_i]
|
||||
url = Proc.new { |key| "/admin/users/list/#{key}" }
|
||||
report.data << { url: url.call(key), key: key, x: level.to_i, y: count }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -416,19 +419,20 @@ class Report
|
|||
def self.report_users_by_type(report)
|
||||
report.data = []
|
||||
|
||||
label = Proc.new { |key| I18n.t("reports.users_by_type.xaxis_labels.#{key}") }
|
||||
label = Proc.new { |x| I18n.t("reports.users_by_type.xaxis_labels.#{x}") }
|
||||
url = Proc.new { |key| "/admin/users/list/#{key}" }
|
||||
|
||||
admins = User.real.admins.count
|
||||
report.data << { key: "admins", x: label.call("admin"), y: admins } if admins > 0
|
||||
report.data << { url: url.call("admins"), icon: "shield", key: "admins", x: label.call("admin"), y: admins } if admins > 0
|
||||
|
||||
moderators = User.real.moderators.count
|
||||
report.data << { key: "moderators", x: label.call("moderator"), y: moderators } if moderators > 0
|
||||
report.data << { url: url.call("moderators"), icon: "shield", key: "moderators", x: label.call("moderator"), y: moderators } if moderators > 0
|
||||
|
||||
suspended = User.real.suspended.count
|
||||
report.data << { key: "suspended", x: label.call("suspended"), y: suspended } if suspended > 0
|
||||
report.data << { url: url.call("suspended"), icon: "ban", key: "suspended", x: label.call("suspended"), y: suspended } if suspended > 0
|
||||
|
||||
silenced = User.real.silenced.count
|
||||
report.data << { key: "silenced", x: label.call("silenced"), y: silenced } if silenced > 0
|
||||
report.data << { url: url.call("silenced"), icon: "ban", key: "silenced", x: label.call("silenced"), y: silenced } if silenced > 0
|
||||
end
|
||||
|
||||
def self.report_top_referred_topics(report)
|
||||
|
|
Loading…
Reference in New Issue