FEATURE: allows to limit visible reports and tabs in dashboard (#9598)
This commit is contained in:
parent
71241a50f7
commit
1b2db44678
|
@ -1,6 +1,6 @@
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { makeArray } from "discourse-common/lib/helpers";
|
import { makeArray } from "discourse-common/lib/helpers";
|
||||||
import { alias, or, and, equal, notEmpty } from "@ember/object/computed";
|
import { alias, or, and, equal, notEmpty, not } from "@ember/object/computed";
|
||||||
import EmberObject, { computed, action } from "@ember/object";
|
import EmberObject, { computed, action } from "@ember/object";
|
||||||
import { next } from "@ember/runloop";
|
import { next } from "@ember/runloop";
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
@ -41,7 +41,12 @@ function collapseWeekly(data, average) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNameBindings: ["isEnabled", "isLoading", "dasherizedDataSourceName"],
|
classNameBindings: [
|
||||||
|
"isVisible",
|
||||||
|
"isEnabled",
|
||||||
|
"isLoading",
|
||||||
|
"dasherizedDataSourceName"
|
||||||
|
],
|
||||||
classNames: ["admin-report"],
|
classNames: ["admin-report"],
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
disabledLabel: I18n.t("admin.dashboard.disabled"),
|
disabledLabel: I18n.t("admin.dashboard.disabled"),
|
||||||
|
@ -63,6 +68,7 @@ export default Component.extend({
|
||||||
showDatesOptions: alias("model.dates_filtering"),
|
showDatesOptions: alias("model.dates_filtering"),
|
||||||
showRefresh: or("showDatesOptions", "model.available_filters.length"),
|
showRefresh: or("showDatesOptions", "model.available_filters.length"),
|
||||||
shouldDisplayTrend: and("showTrend", "model.prev_period"),
|
shouldDisplayTrend: and("showTrend", "model.prev_period"),
|
||||||
|
isVisible: not("isHidden"),
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
@ -70,6 +76,13 @@ export default Component.extend({
|
||||||
this._reports = [];
|
this._reports = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isHidden: computed("siteSettings.dashboard_hidden_reports", function() {
|
||||||
|
return (this.siteSettings.dashboard_hidden_reports || "")
|
||||||
|
.split("|")
|
||||||
|
.filter(Boolean)
|
||||||
|
.includes(this.dataSourceName);
|
||||||
|
}),
|
||||||
|
|
||||||
startDate: computed("filters.startDate", function() {
|
startDate: computed("filters.startDate", function() {
|
||||||
if (this.filters && isPresent(this.filters.startDate)) {
|
if (this.filters && isPresent(this.filters.startDate)) {
|
||||||
return moment(this.filters.startDate, "YYYY-MM-DD");
|
return moment(this.filters.startDate, "YYYY-MM-DD");
|
||||||
|
|
|
@ -23,9 +23,44 @@ export default Controller.extend(PeriodComputationMixin, {
|
||||||
|
|
||||||
@discourseComputed("siteSettings.dashboard_general_tab_activity_metrics")
|
@discourseComputed("siteSettings.dashboard_general_tab_activity_metrics")
|
||||||
activityMetrics(metrics) {
|
activityMetrics(metrics) {
|
||||||
return (metrics || "").split("|").filter(m => m);
|
return (metrics || "").split("|").filter(Boolean);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hiddenReports: computed("siteSettings.dashboard_hidden_reports", function() {
|
||||||
|
return (this.siteSettings.dashboard_hidden_reports || "")
|
||||||
|
.split("|")
|
||||||
|
.filter(Boolean);
|
||||||
|
}),
|
||||||
|
|
||||||
|
isActivityMetricsVisible: computed(
|
||||||
|
"activityMetrics",
|
||||||
|
"hiddenReports",
|
||||||
|
function() {
|
||||||
|
return (
|
||||||
|
this.activityMetrics.length &&
|
||||||
|
this.activityMetrics.some(x => !this.hiddenReports.includes(x))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
|
||||||
|
isSearchReportsVisible: computed("hiddenReports", function() {
|
||||||
|
return ["top_referred_topics", "trending_search"].some(
|
||||||
|
x => !this.hiddenReports.includes(x)
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
|
||||||
|
isCommunityHealthVisible: computed("hiddenReports", function() {
|
||||||
|
return [
|
||||||
|
"consolidated_page_views",
|
||||||
|
"signups",
|
||||||
|
"topics",
|
||||||
|
"posts",
|
||||||
|
"dau_by_mau",
|
||||||
|
"daily_engaged_users",
|
||||||
|
"new_contributors"
|
||||||
|
].some(x => !this.hiddenReports.includes(x));
|
||||||
|
}),
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
activityMetricsFilters() {
|
activityMetricsFilters() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import PeriodComputationMixin from "admin/mixins/period-computation";
|
import PeriodComputationMixin from "admin/mixins/period-computation";
|
||||||
|
import { computed } from "@ember/object";
|
||||||
|
|
||||||
export default Controller.extend(PeriodComputationMixin, {
|
export default Controller.extend(PeriodComputationMixin, {
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
|
@ -13,6 +14,16 @@ export default Controller.extend(PeriodComputationMixin, {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isModeratorsActivityVisible: computed(
|
||||||
|
"siteSettings.dashboard_hidden_reports",
|
||||||
|
function() {
|
||||||
|
return !(this.siteSettings.dashboard_hidden_reports || "")
|
||||||
|
.split("|")
|
||||||
|
.filter(Boolean)
|
||||||
|
.includes("moderators_activity");
|
||||||
|
}
|
||||||
|
),
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
userFlaggingRatioOptions() {
|
userFlaggingRatioOptions() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -8,17 +8,27 @@ const { get } = Ember;
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
filter: null,
|
filter: null,
|
||||||
|
|
||||||
@discourseComputed("model.[]", "filter")
|
@discourseComputed(
|
||||||
|
"model.[]",
|
||||||
|
"filter",
|
||||||
|
"siteSettings.dashboard_hidden_reports"
|
||||||
|
)
|
||||||
filterReports(reports, filter) {
|
filterReports(reports, filter) {
|
||||||
if (filter) {
|
if (filter) {
|
||||||
filter = filter.toLowerCase();
|
filter = filter.toLowerCase();
|
||||||
return reports.filter(report => {
|
reports = reports.filter(report => {
|
||||||
return (
|
return (
|
||||||
(get(report, "title") || "").toLowerCase().indexOf(filter) > -1 ||
|
(get(report, "title") || "").toLowerCase().indexOf(filter) > -1 ||
|
||||||
(get(report, "description") || "").toLowerCase().indexOf(filter) > -1
|
(get(report, "description") || "").toLowerCase().indexOf(filter) > -1
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hiddenReports = (this.siteSettings.dashboard_hidden_reports || "")
|
||||||
|
.split("|")
|
||||||
|
.filter(Boolean);
|
||||||
|
reports = reports.filter(report => !hiddenReports.includes(report.type));
|
||||||
|
|
||||||
return reports;
|
return reports;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { inject } from "@ember/controller";
|
import Controller, { inject } from "@ember/controller";
|
||||||
import Controller from "@ember/controller";
|
|
||||||
import { setting } from "discourse/lib/computed";
|
import { setting } from "discourse/lib/computed";
|
||||||
|
import { computed } from "@ember/object";
|
||||||
import AdminDashboard from "admin/models/admin-dashboard";
|
import AdminDashboard from "admin/models/admin-dashboard";
|
||||||
import VersionCheck from "admin/models/version-check";
|
import VersionCheck from "admin/models/version-check";
|
||||||
|
|
||||||
|
@ -18,6 +18,24 @@ export default Controller.extend({
|
||||||
return this.currentUser.get("admin") && (problemsLength || 0) > 0;
|
return this.currentUser.get("admin") && (problemsLength || 0) > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
visibleTabs: computed("siteSettings.dashboard_visible_tabs", function() {
|
||||||
|
return (this.siteSettings.dashboard_visible_tabs || "")
|
||||||
|
.split("|")
|
||||||
|
.filter(Boolean);
|
||||||
|
}),
|
||||||
|
|
||||||
|
isModerationTabVisible: computed("visibleTabs", function() {
|
||||||
|
return this.visibleTabs.includes("moderation");
|
||||||
|
}),
|
||||||
|
|
||||||
|
isSecurityTabVisible: computed("visibleTabs", function() {
|
||||||
|
return this.visibleTabs.includes("security");
|
||||||
|
}),
|
||||||
|
|
||||||
|
isReportsTabVisible: computed("visibleTabs", function() {
|
||||||
|
return this.visibleTabs.includes("reports");
|
||||||
|
}),
|
||||||
|
|
||||||
fetchProblems() {
|
fetchProblems() {
|
||||||
if (this.isLoadingProblems) return;
|
if (this.isLoadingProblems) return;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{{#if isEnabled}}
|
{{#unless isHidden}}
|
||||||
|
{{#if isEnabled}}
|
||||||
{{#conditional-loading-section isLoading=isLoading}}
|
{{#conditional-loading-section isLoading=isLoading}}
|
||||||
{{#if showHeader}}
|
{{#if showHeader}}
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
@ -188,8 +189,9 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/conditional-loading-section}}
|
{{/conditional-loading-section}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
{{html-safe disabledLabel}}
|
{{html-safe disabledLabel}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
|
|
|
@ -22,21 +22,30 @@
|
||||||
{{i18n "admin.dashboard.general_tab"}}
|
{{i18n "admin.dashboard.general_tab"}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{{#if isModerationTabVisible}}
|
||||||
<li class="navigation-item moderation">
|
<li class="navigation-item moderation">
|
||||||
{{#link-to "admin.dashboardModeration" class="navigation-link"}}
|
{{#link-to "admin.dashboardModeration" class="navigation-link"}}
|
||||||
{{i18n "admin.dashboard.moderation_tab"}}
|
{{i18n "admin.dashboard.moderation_tab"}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</li>
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isSecurityTabVisible}}
|
||||||
<li class="navigation-item security">
|
<li class="navigation-item security">
|
||||||
{{#link-to "admin.dashboardSecurity" class="navigation-link"}}
|
{{#link-to "admin.dashboardSecurity" class="navigation-link"}}
|
||||||
{{i18n "admin.dashboard.security_tab"}}
|
{{i18n "admin.dashboard.security_tab"}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</li>
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isReportsTabVisible}}
|
||||||
<li class="navigation-item reports">
|
<li class="navigation-item reports">
|
||||||
{{#link-to "admin.dashboardReports" class="navigation-link"}}
|
{{#link-to "admin.dashboardReports" class="navigation-link"}}
|
||||||
{{i18n "admin.dashboard.reports_tab"}}
|
{{i18n "admin.dashboard.reports_tab"}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</li>
|
</li>
|
||||||
|
{{/if}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{{#conditional-loading-spinner condition=isLoading}}
|
{{#conditional-loading-spinner condition=isLoading}}
|
||||||
{{plugin-outlet name="admin-dashboard-general-top"}}
|
{{plugin-outlet name="admin-dashboard-general-top"}}
|
||||||
|
|
||||||
|
{{#if isCommunityHealthVisible}}
|
||||||
<div class="community-health section">
|
<div class="community-health section">
|
||||||
<div class="period-section">
|
<div class="period-section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
|
@ -58,9 +59,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="section-columns">
|
<div class="section-columns">
|
||||||
<div class="section-column">
|
<div class="section-column">
|
||||||
|
{{#if isActivityMetricsVisible}}
|
||||||
{{#if activityMetrics.length}}
|
{{#if activityMetrics.length}}
|
||||||
<div class="admin-report activity-metrics">
|
<div class="admin-report activity-metrics">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
@ -93,6 +96,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="user-metrics">
|
<div class="user-metrics">
|
||||||
{{#conditional-loading-section isLoading=isLoading}}
|
{{#conditional-loading-section isLoading=isLoading}}
|
||||||
|
@ -130,6 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{#if isSearchReportsVisible}}
|
||||||
<div class="section-column">
|
<div class="section-column">
|
||||||
{{admin-report
|
{{admin-report
|
||||||
filters=topReferredTopicsFilters
|
filters=topReferredTopicsFilters
|
||||||
|
@ -144,6 +149,7 @@
|
||||||
disabledLabel=trendingSearchDisabledLabel}}
|
disabledLabel=trendingSearchDisabledLabel}}
|
||||||
{{html-safe (i18n "admin.dashboard.reports.trending_search.more" basePath=basePath)}}
|
{{html-safe (i18n "admin.dashboard.reports.trending_search.more" basePath=basePath)}}
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{plugin-outlet name="admin-dashboard-general-bottom"}}
|
{{plugin-outlet name="admin-dashboard-general-bottom"}}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<div class="sections">
|
<div class="sections">
|
||||||
{{plugin-outlet name="admin-dashboard-moderation-top"}}
|
{{plugin-outlet name="admin-dashboard-moderation-top"}}
|
||||||
|
|
||||||
|
{{#if isModeratorsActivityVisible}}
|
||||||
<div class="moderators-activity section">
|
<div class="moderators-activity section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
<h2>
|
<h2>
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
dataSourceName="moderators_activity"}}
|
dataSourceName="moderators_activity"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="main-section">
|
<div class="main-section">
|
||||||
{{admin-report
|
{{admin-report
|
||||||
|
|
|
@ -2195,6 +2195,8 @@ en:
|
||||||
|
|
||||||
short_title: "The short title will be used on the user's home screen, launcher, or other places where space may be limited. It should be limited to 12 characters."
|
short_title: "The short title will be used on the user's home screen, launcher, or other places where space may be limited. It should be limited to 12 characters."
|
||||||
|
|
||||||
|
dashboard_hidden_reports: "Allow to hide the specified reports from the dashboard."
|
||||||
|
dashboard_visible_tabs: "Choose which dashboard tabs are visible."
|
||||||
dashboard_general_tab_activity_metrics: "Choose reports to be displayed as activity metrics on the general tab."
|
dashboard_general_tab_activity_metrics: "Choose reports to be displayed as activity metrics on the general tab."
|
||||||
|
|
||||||
gravatar_name: "Name of the Gravatar provider"
|
gravatar_name: "Name of the Gravatar provider"
|
||||||
|
|
|
@ -2205,6 +2205,22 @@ tags:
|
||||||
client: true
|
client: true
|
||||||
|
|
||||||
dashboard:
|
dashboard:
|
||||||
|
dashboard_hidden_reports:
|
||||||
|
client: true
|
||||||
|
type: list
|
||||||
|
list_type: compact
|
||||||
|
default: ""
|
||||||
|
allow_any: true
|
||||||
|
dashboard_visible_tabs:
|
||||||
|
client: true
|
||||||
|
type: list
|
||||||
|
list_type: compact
|
||||||
|
default: "moderation|security|reports"
|
||||||
|
allow_any: false
|
||||||
|
choices:
|
||||||
|
- moderation
|
||||||
|
- security
|
||||||
|
- reports
|
||||||
dashboard_general_tab_activity_metrics:
|
dashboard_general_tab_activity_metrics:
|
||||||
client: true
|
client: true
|
||||||
type: list
|
type: list
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { acceptance } from "helpers/qunit-helpers";
|
||||||
acceptance("Dashboard", {
|
acceptance("Dashboard", {
|
||||||
loggedIn: true,
|
loggedIn: true,
|
||||||
settings: {
|
settings: {
|
||||||
|
dashboard_visible_tabs: "moderation|security|reports",
|
||||||
dashboard_general_tab_activity_metrics: "page_view_total_reqs"
|
dashboard_general_tab_activity_metrics: "page_view_total_reqs"
|
||||||
},
|
},
|
||||||
site: {
|
site: {
|
||||||
|
@ -20,8 +21,9 @@ acceptance("Dashboard", {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test("Dashboard", async assert => {
|
QUnit.test("default", async assert => {
|
||||||
await visit("/admin");
|
await visit("/admin");
|
||||||
|
|
||||||
assert.ok(exists(".dashboard"), "has dashboard-next class");
|
assert.ok(exists(".dashboard"), "has dashboard-next class");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -57,7 +59,7 @@ QUnit.test("general tab", async assert => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test("general tab - activity metrics", async assert => {
|
QUnit.test("activity metrics", async assert => {
|
||||||
await visit("/admin");
|
await visit("/admin");
|
||||||
|
|
||||||
assert.ok(exists(".admin-report.page-view-total-reqs .today-count"));
|
assert.ok(exists(".admin-report.page-view-total-reqs .today-count"));
|
||||||
|
@ -100,7 +102,7 @@ QUnit.test("reports tab", async assert => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test("report filters", async assert => {
|
QUnit.test("reports filters", async assert => {
|
||||||
await visit(
|
await visit(
|
||||||
'/admin/reports/signups_with_groups?end_date=2018-07-16&filters=%7B"group"%3A88%7D&start_date=2018-06-16'
|
'/admin/reports/signups_with_groups?end_date=2018-07-16&filters=%7B"group"%3A88%7D&start_date=2018-06-16'
|
||||||
);
|
);
|
||||||
|
@ -113,3 +115,41 @@ QUnit.test("report filters", async assert => {
|
||||||
"its set the value of the filter from the query params"
|
"its set the value of the filter from the query params"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
acceptance("Dashboard: dashboard_visible_tabs", {
|
||||||
|
loggedIn: true,
|
||||||
|
settings: {
|
||||||
|
dashboard_visible_tabs: "general|security|reports"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("visible tabs", async assert => {
|
||||||
|
await visit("/admin");
|
||||||
|
|
||||||
|
assert.ok(exists(".dashboard .navigation-item.general"), "general tab");
|
||||||
|
assert.notOk(
|
||||||
|
exists(".dashboard .navigation-item.moderation"),
|
||||||
|
"moderation tab"
|
||||||
|
);
|
||||||
|
assert.ok(exists(".dashboard .navigation-item.security"), "security tab");
|
||||||
|
assert.ok(exists(".dashboard .navigation-item.reports"), "reports tab");
|
||||||
|
});
|
||||||
|
|
||||||
|
acceptance("Dashboard: dashboard_hidden_reports", {
|
||||||
|
loggedIn: true,
|
||||||
|
settings: {
|
||||||
|
dashboard_visible_tabs: "reports",
|
||||||
|
dashboard_hidden_reports: "posts|dau_by_mau"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("hidden reports", async assert => {
|
||||||
|
await visit("/admin");
|
||||||
|
|
||||||
|
assert.ok(exists(".admin-report.signups.is-visible"), "signups report");
|
||||||
|
assert.notOk(exists(".admin-report.is-visible.posts"), "posts report");
|
||||||
|
assert.notOk(
|
||||||
|
exists(".admin-report.is-visible.dau-by-mau"),
|
||||||
|
"dau-by-mau report"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue