UX: minor fixes to new dashboard UI

- adds a link to search log
- display a text if log search queries is disabled
- adds link to trust level and user types
- adds a description for eeach report when browsing a report directly
This commit is contained in:
Joffrey JAFFEUX 2018-05-14 14:23:51 +02:00 committed by GitHub
parent 8232aba743
commit ba0cec2091
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 120 additions and 73 deletions

View File

@ -6,8 +6,11 @@ import { number } from 'discourse/lib/formatter';
export default Ember.Component.extend(AsyncReport, { export default Ember.Component.extend(AsyncReport, {
classNames: ["dashboard-table"], classNames: ["dashboard-table"],
classNameBindings : ["isDisabled"],
help: null, help: null,
helpPage: null, helpPage: null,
isDisabled: Ember.computed.not("siteSettings.log_search_queries"),
disabledLabel: "admin.dashboard.reports.disabled",
@computed("report") @computed("report")
values(report) { values(report) {
@ -29,6 +32,8 @@ export default Ember.Component.extend(AsyncReport, {
}, },
fetchReport() { fetchReport() {
if (this.get("isDisabled")) return;
this.set("isLoading", true); this.set("isLoading", true);
let payload = { data: { async: true } }; let payload = { data: { async: true } };

View File

@ -1,9 +1,9 @@
import { setting } from 'discourse/lib/computed'; import { setting } from "discourse/lib/computed";
import DiscourseURL from "discourse/lib/url"; import DiscourseURL from "discourse/lib/url";
import computed from "ember-addons/ember-computed-decorators"; import computed from "ember-addons/ember-computed-decorators";
import AdminDashboardNext from "admin/models/admin-dashboard-next"; import AdminDashboardNext from "admin/models/admin-dashboard-next";
import Report from "admin/models/report"; import Report from "admin/models/report";
import VersionCheck from 'admin/models/version-check'; import VersionCheck from "admin/models/version-check";
const PROBLEMS_CHECK_MINUTES = 1; const PROBLEMS_CHECK_MINUTES = 1;
@ -13,26 +13,25 @@ export default Ember.Controller.extend({
isLoading: false, isLoading: false,
dashboardFetchedAt: null, dashboardFetchedAt: null,
exceptionController: Ember.inject.controller("exception"), exceptionController: Ember.inject.controller("exception"),
showVersionChecks: setting('version_checks'), showVersionChecks: setting("version_checks"),
diskSpace: Ember.computed.alias("model.attributes.disk_space"), diskSpace: Ember.computed.alias("model.attributes.disk_space"),
logSearchQueriesEnabled: setting("log_search_queries"),
availablePeriods: ["yearly", "quarterly", "monthly", "weekly"], availablePeriods: ["yearly", "quarterly", "monthly", "weekly"],
@computed('problems.length') @computed("problems.length")
foundProblems(problemsLength) { foundProblems(problemsLength) {
return this.currentUser.get('admin') && (problemsLength || 0) > 0; return this.currentUser.get("admin") && (problemsLength || 0) > 0;
}, },
@computed("foundProblems")
@computed('foundProblems')
thereWereProblems(foundProblems) { thereWereProblems(foundProblems) {
if (!this.currentUser.get('admin')) { return false; } if (!this.currentUser.get("admin")) { return false; }
if (foundProblems) { if (foundProblems) {
this.set('hadProblems', true); this.set("hadProblems", true);
return true; return true;
} else { } else {
return this.get('hadProblems') || false; return this.get("hadProblems") || false;
} }
}, },
@ -47,7 +46,7 @@ export default Ember.Controller.extend({
AdminDashboardNext.find().then(adminDashboardNextModel => { AdminDashboardNext.find().then(adminDashboardNextModel => {
if (versionChecks) { if (versionChecks) {
this.set('versionCheck', VersionCheck.create(adminDashboardNextModel.version_check)); this.set("versionCheck", VersionCheck.create(adminDashboardNextModel.version_check));
} }
this.setProperties({ this.setProperties({
@ -63,29 +62,29 @@ export default Ember.Controller.extend({
}); });
} }
if (!this.get('problemsFetchedAt') || moment().subtract(PROBLEMS_CHECK_MINUTES, 'minutes').toDate() > this.get('problemsFetchedAt')) { if (!this.get("problemsFetchedAt") || moment().subtract(PROBLEMS_CHECK_MINUTES, "minutes").toDate() > this.get("problemsFetchedAt")) {
this.loadProblems(); this.loadProblems();
} }
}, },
loadProblems() { loadProblems() {
this.set('loadingProblems', true); this.set("loadingProblems", true);
this.set('problemsFetchedAt', new Date()); this.set("problemsFetchedAt", new Date());
AdminDashboardNext.fetchProblems().then(d => { AdminDashboardNext.fetchProblems().then(d => {
this.set('problems', d.problems); this.set("problems", d.problems);
}).finally(() => { }).finally(() => {
this.set('loadingProblems', false); this.set("loadingProblems", false);
}); });
}, },
@computed('problemsFetchedAt') @computed("problemsFetchedAt")
problemsTimestamp(problemsFetchedAt) { problemsTimestamp(problemsFetchedAt) {
return moment(problemsFetchedAt).locale('en').format('LLL'); return moment(problemsFetchedAt).locale("en").format("LLL");
}, },
@computed("period") @computed("period")
startDate(period) { startDate(period) {
let fullDay = moment().locale('en').utc().subtract(1, "day"); let fullDay = moment().locale("en").utc().subtract(1, "day");
switch (period) { switch (period) {
case "yearly": case "yearly":
@ -107,12 +106,12 @@ export default Ember.Controller.extend({
@computed() @computed()
lastWeek() { lastWeek() {
return moment().locale('en').utc().endOf("day").subtract(1, "week"); return moment().locale("en").utc().endOf("day").subtract(1, "week");
}, },
@computed() @computed()
endDate() { endDate() {
return moment().locale('en').utc().subtract(1, "day").endOf("day"); return moment().locale("en").utc().subtract(1, "day").endOf("day");
}, },
@computed("updated_at") @computed("updated_at")

View File

@ -47,6 +47,8 @@ export default Ember.Mixin.create({
loadReport() {}, loadReport() {},
fetchReport() {},
@computed("dataSourceName") @computed("dataSourceName")
dataSource(dataSourceName) { dataSource(dataSourceName) {
return `/admin/reports/${dataSourceName}`; return `/admin/reports/${dataSourceName}`;

View File

@ -18,9 +18,13 @@
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
{{#each values as |value|}} {{#unless hasBlock}}
<td>{{number value}}</td> {{#each values as |value|}}
{{/each}} <td>{{number value}}</td>
{{/each}}
{{else}}
{{yield (hash report=report)}}
{{/unless}}
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -1,31 +1,37 @@
{{#conditional-loading-section isLoading=isLoading title=report.title}} {{#if isDisabled}}
<div class="table-title"> {{{i18n disabledLabel}}}
<h3>{{report.title}}</h3> {{else}}
{{#conditional-loading-section isLoading=isLoading title=report.title}}
<div class="table-title">
<h3>{{report.title}}</h3>
{{#if help}} {{#if help}}
<a href="{{helpPage}}">{{i18n help}}</a> <a href="{{helpPage}}">{{i18n help}}</a>
{{/if}} {{/if}}
</div> </div>
<div class="table-container"> <div class="table-container">
<table> <table>
<thead> <thead>
<tr>
{{#each labels as |label|}}
<th>{{label}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each values as |value|}}
<tr> <tr>
{{#each value as |v|}} {{#each labels as |label|}}
<td>{{v}}</td> <th>{{label}}</th>
{{/each}} {{/each}}
</tr> </tr>
{{/each}} </thead>
</tbody>
</table> <tbody>
</div> {{#each values as |value|}}
{{/conditional-loading-section}} <tr>
{{#each value as |v|}}
<td>{{v}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
{{yield}}
</div>
{{/conditional-loading-section}}
{{/if}}

View File

@ -1,14 +1,14 @@
{{plugin-outlet name="admin-dashboard-top"}} {{plugin-outlet name="admin-dashboard-top"}}
<div class="section-top"> <div class="section-top">
{{#if showVersionChecks}} {{#if showVersionChecks}}
<div class="dashboard-left"> <div class="dashboard-left">
{{partial 'admin/templates/version-checks'}} {{partial 'admin/templates/version-checks'}}
</div> </div>
<div class="dashboard-right"> <div class="dashboard-right">
{{partial 'admin/templates/dashboard-problems'}} {{partial 'admin/templates/dashboard-problems'}}
</div> </div>
{{/if}} {{/if}}
<div class='clearfix'></div> <div class='clearfix'></div>
</div> </div>
@ -85,13 +85,25 @@
{{/conditional-loading-section}} {{/conditional-loading-section}}
</div> </div>
{{dashboard-inline-table {{#dashboard-inline-table dataSourceName="users_by_type" lastRefreshedAt=lastRefreshedAt as |context|}}
dataSourceName="users_by_type" {{#each context.report.data as |data|}}
lastRefreshedAt=lastRefreshedAt}} <td>
<a href="/admin/users/list/{{data.key}}">
{{number data.y}}
</a>
</td>
{{/each}}
{{/dashboard-inline-table}}
{{dashboard-inline-table {{#dashboard-inline-table dataSourceName="users_by_trust_level" lastRefreshedAt=lastRefreshedAt as |context|}}
dataSourceName="users_by_trust_level" {{#each context.report.data as |data|}}
lastRefreshedAt=lastRefreshedAt}} <td>
<a href="/admin/users/list/{{data.key}}">
{{number data.y}}
</a>
</td>
{{/each}}
{{/dashboard-inline-table}}
{{#conditional-loading-section isLoading=isLoading title=(i18n "admin.dashboard.backups")}} {{#conditional-loading-section isLoading=isLoading title=(i18n "admin.dashboard.backups")}}
<div class="misc"> <div class="misc">
@ -135,9 +147,13 @@
</div> </div>
<div class="section-column"> <div class="section-column">
{{dashboard-table-trending-search {{#dashboard-table-trending-search
dataSourceName="trending_search" dataSourceName="trending_search"
isEnabled=logSearchQueriesEnabled
disabledLabel="admin.dashboard.reports.trending_search.disabled"
startDate=lastWeek startDate=lastWeek
endDate=endDate}} endDate=endDate}}
{{{i18n "admin.dashboard.reports.trending_search.more"}}}
{{/dashboard-table-trending-search}}
</div> </div>
</div> </div>

View File

@ -1,5 +1,9 @@
<h3>{{model.title}}</h3> <h3>{{model.title}}</h3>
{{#if model.description}}
<p>{{model.description}}</p>
{{/if}}
<div class="admin-reports-filter"> <div class="admin-reports-filter">
{{i18n 'admin.dashboard.reports.start_date'}} {{date-picker-past value=startDate defaultDate=startDate}} {{i18n 'admin.dashboard.reports.start_date'}} {{date-picker-past value=startDate defaultDate=startDate}}
{{i18n 'admin.dashboard.reports.end_date'}} {{date-picker-past value=endDate defaultDate=endDate}} {{i18n 'admin.dashboard.reports.end_date'}} {{date-picker-past value=endDate defaultDate=endDate}}

View File

@ -65,6 +65,11 @@
.dashboard-table { .dashboard-table {
margin-bottom: 1em; margin-bottom: 1em;
&.is-disabled {
background: $primary-low;
padding: 1em;
}
@include small-width { @include small-width {
table { table {
tbody tr td { tbody tr td {
@ -91,7 +96,7 @@
table-layout: fixed; table-layout: fixed;
thead { thead {
border: 1px solid $primary-low; border: 1px solid $primary-low;
tr { tr {
background: $primary-low; background: $primary-low;
th { th {

View File

@ -324,7 +324,7 @@ class Report
def self.report_users_by_trust_level(report) def self.report_users_by_trust_level(report)
report.data = [] report.data = []
User.real.group('trust_level').count.sort.each do |level, count| User.real.group('trust_level').count.sort.each do |level, count|
report.data << { x: level.to_i, y: count } report.data << { key: TrustLevel.levels[level.to_i], x: level.to_i, y: count }
end end
end end
@ -401,16 +401,16 @@ class Report
label = Proc.new { |key| I18n.t("reports.users_by_type.xaxis_labels.#{key}") } label = Proc.new { |key| I18n.t("reports.users_by_type.xaxis_labels.#{key}") }
admins = User.real.admins.count admins = User.real.admins.count
report.data << { x: label.call("admin"), y: admins } if admins > 0 report.data << { key: "admin", x: label.call("admin"), y: admins } if admins > 0
moderators = User.real.moderators.count moderators = User.real.moderators.count
report.data << { x: label.call("moderator"), y: moderators } if moderators > 0 report.data << { key: "moderator", x: label.call("moderator"), y: moderators } if moderators > 0
suspended = User.real.suspended.count suspended = User.real.suspended.count
report.data << { x: label.call("suspended"), y: suspended } if suspended > 0 report.data << { key: "suspended", x: label.call("suspended"), y: suspended } if suspended > 0
silenced = User.real.silenced.count silenced = User.real.silenced.count
report.data << { x: label.call("silenced"), y: silenced } if silenced > 0 report.data << { key: "silenced", x: label.call("silenced"), y: silenced } if silenced > 0
end end
def self.report_trending_search(report) def self.report_trending_search(report)

View File

@ -2765,6 +2765,10 @@ en:
start_date: "Start Date" start_date: "Start Date"
end_date: "End Date" end_date: "End Date"
groups: "All groups" groups: "All groups"
disabled: "This report is disabled"
trending_search:
more: '<a href="/admin/logs/search_logs">Search logs</a>'
disabled: 'Trending search report is disabled. Enable <a href="/admin/site_settings/category/all_results?filter=log%20search%20queries">log search queries</a> to collect data.'
commits: commits:
latest_changes: "Latest changes: please update often!" latest_changes: "Latest changes: please update often!"

View File

@ -1323,7 +1323,9 @@ search:
search_recent_posts_size: search_recent_posts_size:
default: 100000 default: 100000
max: 100000 max: 100000
log_search_queries: true log_search_queries:
client: true
default: true
search_query_log_max_size: search_query_log_max_size:
default: 1000000 default: 1000000
max: 1000000 max: 1000000