FEATURE: part 2 of dashboard improvements

- moderation tab
- sorting/pagination
- improved third party reports support
- trending charts
- better perf
- many fixes
- refactoring
- new reports

Co-Authored-By: Simon Cossar <scossar@users.noreply.github.com>
This commit is contained in:
Joffrey JAFFEUX
2018-07-19 14:33:11 -04:00
committed by GitHub
parent 4e09206061
commit 1a78e12f4e
76 changed files with 3177 additions and 1484 deletions
@@ -7,25 +7,18 @@ acceptance("Dashboard Next", {
QUnit.test("Visit dashboard next page", async assert => {
await visit("/admin");
assert.ok($(".dashboard-next").length, "has dashboard-next class");
assert.ok($(".dashboard-mini-chart.signups").length, "has a signups chart");
assert.ok($(".dashboard-mini-chart.posts").length, "has a posts chart");
assert.ok(exists(".dashboard-next"), "has dashboard-next class");
assert.ok(exists(".admin-report.signups"), "signups report");
assert.ok(exists(".admin-report.posts"), "posts report");
assert.ok(exists(".admin-report.dau-by-mau"), "dau-by-mau report");
assert.ok(
$(".dashboard-mini-chart.dau_by_mau").length,
"has a dau_by_mau chart"
exists(".admin-report.daily-engaged-users"),
"daily-engaged-users report"
);
assert.ok(
$(".dashboard-mini-chart.daily_engaged_users").length,
"has a daily_engaged_users chart"
);
assert.ok(
$(".dashboard-mini-chart.new_contributors").length,
"has a new_contributors chart"
exists(".admin-report.new-contributors"),
"new-contributors report"
);
assert.equal(
@@ -0,0 +1,130 @@
import componentTest from "helpers/component-test";
moduleForComponent("admin-report", {
integration: true
});
componentTest("default", {
template: "{{admin-report dataSourceName='signups'}}",
test(assert) {
andThen(() => {
assert.ok(exists(".admin-report.signups"));
assert.ok(
exists(".admin-report.table.signups", "it defaults to table mode")
);
assert.equal(
find(".report-header .title")
.text()
.trim(),
"Signups",
"it has a title"
);
assert.equal(
find(".report-header .info").attr("data-tooltip"),
"New account registrations for this period",
"it has a description"
);
assert.equal(
find(".report-body .report-table thead tr th:first-child")
.text()
.trim(),
"Day",
"it has col headers"
);
assert.equal(
find(".report-body .report-table thead tr th:nth-child(2)")
.text()
.trim(),
"Count",
"it has col headers"
);
assert.equal(
find(".report-body .report-table tbody tr:nth-child(1) td:nth-child(1)")
.text()
.trim(),
"June 16, 2018",
"it has rows"
);
assert.equal(
find(".report-body .report-table tbody tr:nth-child(1) td:nth-child(2)")
.text()
.trim(),
"12",
"it has rows"
);
assert.ok(exists(".totals-sample-table"), "it has totals");
});
click(".admin-report-table-header.y .sort-button");
andThen(() => {
assert.equal(
find(".report-body .report-table tbody tr:nth-child(1) td:nth-child(2)")
.text()
.trim(),
"7",
"it can sort rows"
);
});
}
});
componentTest("options", {
template: "{{admin-report dataSourceName='signups' reportOptions=options}}",
beforeEach() {
this.set("options", {
table: {
perPage: 4,
total: false
}
});
},
test(assert) {
andThen(() => {
assert.ok(exists(".pagination"), "it paginates the results");
assert.equal(
find(".pagination button").length,
3,
"it creates the correct number of pages"
);
assert.notOk(exists(".totals-sample-table"), "it hides totals");
});
}
});
componentTest("switch modes", {
template: "{{admin-report dataSourceName='signups'}}",
test(assert) {
click(".mode-button.chart");
andThen(() => {
assert.notOk(
exists(".admin-report.table.signups"),
"it removes the table"
);
assert.ok(exists(".admin-report.chart.signups"), "it shows the chart");
});
}
});
componentTest("timeout", {
template: "{{admin-report dataSourceName='signups_timeout'}}",
test(assert) {
andThen(() => {
assert.ok(exists(".alert-error"), "it displays a timeout error");
});
}
});
@@ -0,0 +1,13 @@
export default {
"/admin/general.json": {
reports: [],
last_backup_taken_at: "2018-04-13T12:51:19.926Z",
updated_at: "2018-04-25T08:06:11.292Z",
disk_space: {
uploads_used: "74.5 KB",
uploads_free: "117 GB",
backups_used: "4.24 GB",
backups_free: "117 GB"
}
}
};
@@ -1,20 +1,7 @@
export default {
"/admin/reports/daily_engaged_users": {
report: {
type: "daily_engaged_users",
title: "Daily Engaged Users",
xaxis: "Day",
yaxis: "Engaged Users",
description: "Number of users that have liked or posted in the last day",
data: null,
total: null,
start_date: "2018-04-03",
end_date: "2018-05-03",
category_id: null,
group_id: null,
prev30Days: null,
labels: null,
report_key: ""
report_key: "daily_engaged_users"
}
}
};
@@ -1,13 +1,5 @@
export default {
"/admin/dashboard-next.json": {
reports: [],
last_backup_taken_at: "2018-04-13T12:51:19.926Z",
updated_at: "2018-04-25T08:06:11.292Z",
disk_space: {
uploads_used: "74.5 KB",
uploads_free: "117 GB",
backups_used: "4.24 GB",
backups_free: "117 GB"
}
updated_at: "2018-04-25T08:06:11.292Z"
}
};
+1 -14
View File
@@ -1,20 +1,7 @@
export default {
"/admin/reports/dau_by_mau": {
report: {
type: "dau_by_mau",
title: "DAU/MAU",
xaxis: "Day",
yaxis: "DAU/MAY",
description: "Percentage of daily active users on monthly active users",
data: null,
total: null,
start_date: "2018-01-26T00:00:00.000Z",
end_date: "2018-04-27T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: 46,
labels: null,
report_key: ""
report_key: "dau_by_mau"
}
}
};
@@ -1,60 +1,7 @@
export default {
"/admin/reports/new_contributors": {
report: {
type: "new_contributors",
title: "New Contributors",
xaxis: "",
yaxis: "",
data: [
{
x: "2018-04-11",
y: 10
},
{
x: "2018-04-12",
y: 10
},
{
x: "2018-04-13",
y: 60
},
{
x: "2018-04-14",
y: 60
},
{
x: "2018-04-15",
y: 10
},
{
x: "2018-04-16",
y: 10
},
{
x: "2018-04-17",
y: 10
},
{
x: "2018-04-19",
y: 10
},
{
x: "2018-04-18",
y: 10
},
{
x: "2018-04-20",
y: 1
}
],
total: 121,
start_date: "2018-03-26T00:00:00.000Z",
end_date: "2018-04-25T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: null,
labels: null,
report_key: ""
report_key: "new_contributors"
}
}
};
+1 -13
View File
@@ -1,19 +1,7 @@
export default {
"/admin/reports/posts": {
report: {
type: "topics",
title: "Topics",
xaxis: "Day",
yaxis: "Number of new posts",
data: null,
total: null,
start_date: "2018-03-26T00:00:00.000Z",
end_date: "2018-04-25T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: 0,
labels: null,
report_key: ""
report_key: "posts"
}
}
};
+66 -43
View File
@@ -4,53 +4,76 @@ export default {
type: "signups",
title: "Signups",
xaxis: "Day",
yaxis: "Number of new users",
yaxis: "Number of signups",
description: "New account registrations for this period",
data: [
{
x: "2018-04-11",
y: 10
},
{
x: "2018-04-12",
y: 10
},
{
x: "2018-04-13",
y: 22
},
{
x: "2018-04-14",
y: 58
},
{
x: "2018-04-15",
y: 10
},
{
x: "2018-04-16",
y: 10
},
{
x: "2018-04-17",
y: 19
},
{
x: "2018-04-18",
y: 12
},
{
x: "2018-04-19",
y: 19
}
{ x: "2018-06-16", y: 12 },
{ x: "2018-06-17", y: 16 },
{ x: "2018-06-18", y: 42 },
{ x: "2018-06-19", y: 38 },
{ x: "2018-06-20", y: 41 },
{ x: "2018-06-21", y: 32 },
{ x: "2018-06-22", y: 23 },
{ x: "2018-06-23", y: 23 },
{ x: "2018-06-24", y: 17 },
{ x: "2018-06-25", y: 27 },
{ x: "2018-06-26", y: 32 },
{ x: "2018-06-27", y: 7 }
],
total: 136,
start_date: "2018-03-26T00:00:00.000Z",
end_date: "2018-04-25T23:59:59.999Z",
start_date: "2018-06-16T00:00:00Z",
end_date: "2018-07-16T23:59:59Z",
prev_data: [
{ x: "2018-05-17", y: 32 },
{ x: "2018-05-18", y: 30 },
{ x: "2018-05-19", y: 12 },
{ x: "2018-05-20", y: 23 },
{ x: "2018-05-21", y: 50 },
{ x: "2018-05-22", y: 39 },
{ x: "2018-05-23", y: 51 },
{ x: "2018-05-24", y: 48 },
{ x: "2018-05-25", y: 37 },
{ x: "2018-05-26", y: 17 },
{ x: "2018-05-27", y: 6 },
{ x: "2018-05-28", y: 20 },
{ x: "2018-05-29", y: 37 },
{ x: "2018-05-30", y: 37 },
{ x: "2018-05-31", y: 37 },
{ x: "2018-06-01", y: 38 },
{ x: "2018-06-02", y: 23 },
{ x: "2018-06-03", y: 18 },
{ x: "2018-06-04", y: 39 },
{ x: "2018-06-05", y: 26 },
{ x: "2018-06-06", y: 39 },
{ x: "2018-06-07", y: 52 },
{ x: "2018-06-08", y: 35 },
{ x: "2018-06-09", y: 19 },
{ x: "2018-06-10", y: 15 },
{ x: "2018-06-11", y: 31 },
{ x: "2018-06-12", y: 38 },
{ x: "2018-06-13", y: 30 },
{ x: "2018-06-14", y: 45 },
{ x: "2018-06-15", y: 37 },
{ x: "2018-06-16", y: 12 }
],
prev_start_date: "2018-05-17T00:00:00Z",
prev_end_date: "2018-06-17T00:00:00Z",
category_id: null,
group_id: null,
prev30Days: 0,
labels: null,
report_key: ""
prev30Days: null,
dates_filtering: true,
report_key: "reports:signups::20180616:20180716::[:prev_period]:",
labels: [
{ type: "date", properties: ["x"], title: "Day" },
{ type: "number", properties: ["y"], title: "Count" }
],
processing: false,
average: false,
percent: false,
higher_is_better: true,
category_filtering: false,
group_filtering: true,
modes: ["table", "chart"],
prev_period: 961
}
}
};
@@ -0,0 +1,35 @@
export default {
"/admin/reports/signups_timeout": {
report: {
type: "signups",
title: "Signups",
xaxis: "Day",
yaxis: "Number of signups",
description: "New account registrations for this period",
data: null,
start_date: "2018-06-16T00:00:00Z",
end_date: "2018-07-16T23:59:59Z",
prev_data: null,
prev_start_date: "2018-05-17T00:00:00Z",
prev_end_date: "2018-06-17T00:00:00Z",
category_id: null,
group_id: null,
prev30Days: null,
dates_filtering: true,
report_key: "reports:signups_timeout::20180616:20180716::[:prev_period]:",
labels: [
{ type: "date", properties: ["x"], title: "Day" },
{ type: "number", properties: ["y"], title: "Count" }
],
processing: false,
average: false,
percent: false,
higher_is_better: true,
category_filtering: false,
group_filtering: true,
modes: ["table", "chart"],
prev_period: 961,
timeout: true
}
}
};
@@ -1,18 +1,7 @@
export default {
"/admin/reports/top_referred_topics": {
report: {
type: "top_referred_topics",
title: "Trending search",
xaxis: "",
yaxis: "",
data: null,
total: null,
start_date: "2018-03-26T00:00:00.000Z",
end_date: "2018-04-25T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: null,
labels: ["Topic", "Visits"]
report_key: "top_referred_topics"
}
}
};
+1 -13
View File
@@ -1,19 +1,7 @@
export default {
"/admin/reports/topics": {
report: {
type: "topics",
title: "Topics",
xaxis: "Day",
yaxis: "Number of new topics",
data: null,
total: null,
start_date: "2018-03-26T00:00:00.000Z",
end_date: "2018-04-25T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: 0,
labels: null,
report_key: ""
report_key: "topics"
}
}
};
@@ -1,19 +1,7 @@
export default {
"/admin/reports/trending_search": {
report: {
type: "trending_search",
title: "Trending search",
xaxis: "",
yaxis: "",
data: null,
total: null,
start_date: "2018-03-26T00:00:00.000Z",
end_date: "2018-04-25T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: null,
labels: ["Term", "Searches", "Unique"],
report_key: ""
report_key: "trending_search"
}
}
};
@@ -1,21 +1,7 @@
export default {
"/admin/reports/users_by_trust_level": {
report: {
type: "users_by_trust_level",
title: "Users per Trust Level",
xaxis: "Trust Level",
yaxis: "Number of Users",
description:
"translation missing: en.reports.users_by_trust_level.description",
data: null,
total: null,
start_date: "2018-03-30T00:00:00.000Z",
end_date: "2018-04-29T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: null,
labels: null,
report_key: ""
report_key: "users_by_trust_level"
}
}
};
+1 -14
View File
@@ -1,20 +1,7 @@
export default {
"/admin/reports/users_by_type": {
report: {
type: "users_by_type",
title: "Users per Type",
xaxis: "Type",
yaxis: "Number of Users",
description: "translation missing: en.reports.users_by_type.description",
data: null,
total: null,
start_date: "2018-03-30T00:00:00.000Z",
end_date: "2018-04-29T23:59:59.999Z",
category_id: null,
group_id: null,
prev30Days: null,
labels: null,
report_key: ""
report_key: "users_by_type"
}
}
};
@@ -391,3 +391,74 @@ QUnit.test("average", assert => {
report.set("average", false);
assert.ok(report.get("lastSevenDaysCount") === 35);
});
QUnit.test("computed labels", assert => {
const data = [
{
username: "joffrey",
user_url: "/admin/users/1/joffrey",
flag_count: 1876,
time_read: 287362,
note: "This is a long note"
}
];
const labels = [
{
type: "link",
properties: ["username", "user_url"],
title: "Username"
},
{ properties: ["flag_count"], title: "Flag count" },
{ type: "seconds", properties: ["time_read"], title: "Time read" },
{ type: "text", properties: ["note"], title: "Note" }
];
const report = Report.create({
type: "topics",
labels,
data
});
const row = report.get("data.0");
const computedLabels = report.get("computedLabels");
const usernameLabel = computedLabels[0];
assert.equal(usernameLabel.property, "username");
assert.equal(usernameLabel.sort_property, "username");
assert.equal(usernameLabel.title, "Username");
const computedUsernameLabel = usernameLabel.compute(row);
assert.equal(
computedUsernameLabel.formatedValue,
'<a href="/admin/users/1/joffrey">joffrey</a>'
);
assert.equal(computedUsernameLabel.type, "link");
assert.equal(computedUsernameLabel.value, "joffrey");
const flagCountLabel = computedLabels[1];
assert.equal(flagCountLabel.property, "flag_count");
assert.equal(flagCountLabel.sort_property, "flag_count");
assert.equal(flagCountLabel.title, "Flag count");
const computedFlagCountLabel = flagCountLabel.compute(row);
assert.equal(computedFlagCountLabel.formatedValue, "1.9k");
assert.equal(computedFlagCountLabel.type, "number");
assert.equal(computedFlagCountLabel.value, 1876);
const timeReadLabel = computedLabels[2];
assert.equal(timeReadLabel.property, "time_read");
assert.equal(timeReadLabel.sort_property, "time_read");
assert.equal(timeReadLabel.title, "Time read");
const computedTimeReadLabel = timeReadLabel.compute(row);
assert.equal(computedTimeReadLabel.formatedValue, "3d");
assert.equal(computedTimeReadLabel.type, "seconds");
assert.equal(computedTimeReadLabel.value, 287362);
const noteLabel = computedLabels[3];
assert.equal(noteLabel.property, "note");
assert.equal(noteLabel.sort_property, "note");
assert.equal(noteLabel.title, "Note");
const computedNoteLabel = noteLabel.compute(row);
assert.equal(computedNoteLabel.formatedValue, "This is a long note");
assert.equal(computedNoteLabel.type, "text");
assert.equal(computedNoteLabel.value, "This is a long note");
});