mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
UX: Apply admin UI guidelines to Reports pages (#30684)
Applies the admin UI guidelines from https://meta.discourse.org/t/creating-consistent-admin-interfaces/326780 to the reports list and single report page for admins.   --------- Co-authored-by: Ella <ella.estigoy@gmail.com>
This commit is contained in:
parent
65dec020b8
commit
dc0bf90069
@ -4,51 +4,13 @@
|
||||
{{#if this.showHeader}}
|
||||
<div class="header">
|
||||
{{#if this.showTitle}}
|
||||
<ul class="breadcrumb">
|
||||
{{#if this.showAllReportsLink}}
|
||||
<li class="item all-reports">
|
||||
<LinkTo @route="adminReports.index" class="report-url">
|
||||
{{i18n "admin.dashboard.all_reports"}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
|
||||
{{#unless this.showNotFoundError}}
|
||||
<li class="item separator">|</li>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
|
||||
{{#unless this.showNotFoundError}}
|
||||
<li class="item report">
|
||||
<a href={{this.model.reportUrl}} class="report-url">
|
||||
{{this.model.title}}
|
||||
</a>
|
||||
|
||||
{{#if this.model.description}}
|
||||
<DTooltip
|
||||
@interactive={{this.model.description_link.length}}
|
||||
>
|
||||
<:trigger>
|
||||
{{d-icon "circle-question"}}
|
||||
</:trigger>
|
||||
<:content>
|
||||
{{#if this.model.description_link}}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={{this.model.description_link}}
|
||||
class="info"
|
||||
>
|
||||
{{this.model.description}}
|
||||
</a>
|
||||
{{else}}
|
||||
<span>{{this.model.description}}</span>
|
||||
{{/if}}
|
||||
</:content>
|
||||
</DTooltip>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/unless}}
|
||||
</ul>
|
||||
{{#unless this.showNotFoundError}}
|
||||
<DPageSubheader
|
||||
@titleLabel={{this.model.title}}
|
||||
@descriptionLabel={{this.model.description}}
|
||||
@learnMoreUrl={{this.model.description_link}}
|
||||
/>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
|
||||
{{#if this.shouldDisplayTrend}}
|
||||
|
@ -40,7 +40,6 @@ export default class AdminReport extends Component {
|
||||
model = null;
|
||||
reportOptions = null;
|
||||
forcedModes = null;
|
||||
showAllReportsLink = false;
|
||||
filters = null;
|
||||
showTrend = false;
|
||||
showHeader = true;
|
||||
|
@ -1,25 +1,29 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { Input } from "@ember/component";
|
||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||
import { LinkTo } from "@ember/routing";
|
||||
import { fn } from "@ember/helper";
|
||||
import { on } from "@ember/modifier";
|
||||
import { service } from "@ember/service";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
|
||||
import dIcon from "discourse/helpers/d-icon";
|
||||
import withEventValue from "discourse/helpers/with-event-value";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { bind } from "discourse/lib/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import AdminSectionLandingItem from "admin/components/admin-section-landing-item";
|
||||
import AdminSectionLandingWrapper from "admin/components/admin-section-landing-wrapper";
|
||||
|
||||
export default class AdminReports extends Component {
|
||||
@service siteSettings;
|
||||
@tracked reports = null;
|
||||
@tracked filter = "";
|
||||
@tracked isLoading = false;
|
||||
@tracked isLoading = true;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.loadReports();
|
||||
}
|
||||
|
||||
@bind
|
||||
loadReports() {
|
||||
this.isLoading = true;
|
||||
ajax("/admin/reports")
|
||||
.then((json) => {
|
||||
this.reports = json.reports;
|
||||
@ -54,39 +58,28 @@ export default class AdminReports extends Component {
|
||||
}
|
||||
|
||||
<template>
|
||||
<div {{didInsert this.loadReports}}>
|
||||
<ConditionalLoadingSpinner @condition={{this.isLoading}}>
|
||||
<div class="admin-reports-header">
|
||||
<h2>{{i18n "admin.reports.title"}}</h2>
|
||||
<Input
|
||||
class="admin-reports-header__filter"
|
||||
<ConditionalLoadingSpinner @condition={{this.isLoading}}>
|
||||
<div class="d-admin-filter admin-reports-header">
|
||||
<div class="admin-filter__input-container">
|
||||
<input
|
||||
type="text"
|
||||
class="admin-filter__input admin-reports-header__filter"
|
||||
placeholder={{i18n "admin.filter_reports"}}
|
||||
@value={{this.filter}}
|
||||
value={{this.filter}}
|
||||
{{on "input" (withEventValue (fn (mut this.filter)))}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
{{dIcon "book"}}
|
||||
{{htmlSafe (i18n "admin.reports.meta_doc")}}
|
||||
</div>
|
||||
|
||||
<ul class="admin-reports-list">
|
||||
{{#each this.filteredReports as |report|}}
|
||||
<li class="admin-reports-list__report">
|
||||
<LinkTo @route="adminReports.show" @model={{report.type}}>
|
||||
<h3
|
||||
class="admin-reports-list__report-title"
|
||||
>{{report.title}}</h3>
|
||||
{{#if report.description}}
|
||||
<p class="admin-reports-list__report-description">
|
||||
{{report.description}}
|
||||
</p>
|
||||
{{/if}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</ConditionalLoadingSpinner>
|
||||
</div>
|
||||
</div>
|
||||
<AdminSectionLandingWrapper class="admin-reports-list">
|
||||
{{#each this.filteredReports as |report|}}
|
||||
<AdminSectionLandingItem
|
||||
@titleLabelTranslated={{report.title}}
|
||||
@descriptionLabelTranslated={{report.description}}
|
||||
@titleRoute="adminReports.show"
|
||||
@titleRouteModel={{report.type}}
|
||||
/>
|
||||
{{/each}}
|
||||
</AdminSectionLandingWrapper>
|
||||
</ConditionalLoadingSpinner>
|
||||
</template>
|
||||
}
|
||||
|
@ -54,9 +54,16 @@ export default class AdminSectionLandingItem extends Component {
|
||||
{{/if}}
|
||||
|
||||
{{#if @titleRoute}}
|
||||
<LinkTo @route={{@titleRoute}}><h3
|
||||
class="admin-section-landing-item__title"
|
||||
>{{this.title}}</h3></LinkTo>
|
||||
{{#if @titleRouteModel}}
|
||||
<LinkTo @route={{@titleRoute}} @model={{@titleRouteModel}}><h3
|
||||
class="admin-section-landing-item__title"
|
||||
>{{this.title}}</h3></LinkTo>
|
||||
{{else}}
|
||||
<LinkTo @route={{@titleRoute}}><h3
|
||||
class="admin-section-landing-item__title"
|
||||
>{{this.title}}</h3></LinkTo>
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
<h3 class="admin-section-landing-item__title">{{this.title}}</h3>
|
||||
{{/if}}
|
||||
|
@ -1 +1,20 @@
|
||||
<AdminReports />
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.reports.title"}}
|
||||
@descriptionLabel={{i18n "admin.reports.meta_doc"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/-/240233"
|
||||
@hideTabs={{true}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/reports"
|
||||
@label={{i18n "admin.reports.sidebar_title"}}
|
||||
/>
|
||||
</:breadcrumbs>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
<div class="admin-config-area__full-width">
|
||||
<AdminReports />
|
||||
</div>
|
||||
</div>
|
@ -1,8 +1,12 @@
|
||||
<AdminReport
|
||||
@showAllReportsLink={{true}}
|
||||
@dataSourceName={{this.model.type}}
|
||||
@filters={{this.model}}
|
||||
@reportOptions={{this.reportOptions}}
|
||||
@showFilteringUI={{true}}
|
||||
@onRefresh={{route-action "onParamsChange"}}
|
||||
/>
|
||||
<BackButton @route="adminReports" @label="admin.reports.back" />
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
<div class="admin-config-area">
|
||||
<AdminReport
|
||||
@dataSourceName={{this.model.type}}
|
||||
@filters={{this.model}}
|
||||
@reportOptions={{this.reportOptions}}
|
||||
@showFilteringUI={{true}}
|
||||
@onRefresh={{route-action "onParamsChange"}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
@ -100,11 +100,15 @@ acceptance("Admin Sidebar - Sections", function (needs) {
|
||||
await click(".sidebar-toggle-all-sections");
|
||||
await click(".sidebar-section-link[data-link-name='admin_all_reports']");
|
||||
|
||||
assert.dom(".admin-reports-list__report").exists({ count: 1 });
|
||||
assert
|
||||
.dom(".admin-reports-list .admin-section-landing-item__content")
|
||||
.exists({ count: 1 });
|
||||
|
||||
await fillIn(".admin-reports-header__filter", "flags");
|
||||
|
||||
assert.dom(".admin-reports-list__report").doesNotExist();
|
||||
assert
|
||||
.dom(".admin-reports-list .admin-section-landing-item__content")
|
||||
.doesNotExist();
|
||||
|
||||
await click(
|
||||
".sidebar-section-link[data-link-name='admin_login_and_authentication']"
|
||||
@ -112,13 +116,13 @@ acceptance("Admin Sidebar - Sections", function (needs) {
|
||||
await click(".sidebar-section-link[data-link-name='admin_all_reports']");
|
||||
|
||||
assert
|
||||
.dom(".admin-reports-list__report")
|
||||
.dom(".admin-reports-list .admin-section-landing-item__content")
|
||||
.exists({ count: 1 }, "navigating back and forth resets filter");
|
||||
|
||||
await fillIn(".admin-reports-header__filter", "activities");
|
||||
|
||||
assert
|
||||
.dom(".admin-reports-list__report")
|
||||
.dom(".admin-reports-list .admin-section-landing-item__content")
|
||||
.exists({ count: 1 }, "filter is case insensitive");
|
||||
});
|
||||
});
|
||||
|
@ -73,23 +73,35 @@ acceptance("Dashboard", function (needs) {
|
||||
await visit("/admin");
|
||||
await click(".dashboard .navigation-item.reports .navigation-link");
|
||||
|
||||
assert.dom(".dashboard .admin-reports-list__report").exists({ count: 1 });
|
||||
assert
|
||||
.dom(
|
||||
".dashboard .admin-reports-list .admin-section-landing-item__content"
|
||||
)
|
||||
.exists({ count: 1 });
|
||||
|
||||
await fillIn(".dashboard .admin-reports-header__filter", "flags");
|
||||
|
||||
assert.dom(".dashboard .admin-reports-list__report").doesNotExist();
|
||||
assert
|
||||
.dom(
|
||||
".dashboard .admin-reports-list .admin-section-landing-item__content"
|
||||
)
|
||||
.doesNotExist();
|
||||
|
||||
await click(".dashboard .navigation-item.security .navigation-link");
|
||||
await click(".dashboard .navigation-item.reports .navigation-link");
|
||||
|
||||
assert
|
||||
.dom(".dashboard .admin-reports-list__report")
|
||||
.dom(
|
||||
".dashboard .admin-reports-list .admin-section-landing-item__content"
|
||||
)
|
||||
.exists({ count: 1 }, "navigating back and forth resets filter");
|
||||
|
||||
await fillIn(".dashboard .admin-reports-header__filter", "activities");
|
||||
|
||||
assert
|
||||
.dom(".dashboard .admin-reports-list__report")
|
||||
.dom(
|
||||
".dashboard .admin-reports-list .admin-section-landing-item__content"
|
||||
)
|
||||
.exists({ count: 1 }, "filter is case insensitive");
|
||||
});
|
||||
|
||||
|
@ -8,15 +8,19 @@ acceptance("Reports", function (needs) {
|
||||
test("Visit reports page", async function (assert) {
|
||||
await visit("/admin/reports");
|
||||
|
||||
assert.dom(".admin-reports-list__report").exists({ count: 1 });
|
||||
assert
|
||||
.dom(".admin-reports-list .admin-section-landing-item__content")
|
||||
.exists({ count: 1 });
|
||||
|
||||
assert
|
||||
.dom(".admin-reports-list__report .admin-reports-list__report-title")
|
||||
.dom(
|
||||
".admin-reports-list .admin-section-landing-item__content .admin-section-landing-item__title"
|
||||
)
|
||||
.hasHtml("My report");
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".admin-reports-list__report .admin-reports-list__report-description"
|
||||
".admin-reports-list .admin-section-landing-item__content .admin-section-landing-item__description"
|
||||
)
|
||||
.hasHtml("List of my activities");
|
||||
});
|
||||
|
@ -12,13 +12,15 @@ module("Integration | Component | admin-report", function (hooks) {
|
||||
|
||||
assert.dom(".admin-report.signups").exists();
|
||||
assert.dom(".admin-report-table").exists("defaults to table mode");
|
||||
assert.dom(".header .item.report").hasText("Signups", "has a title");
|
||||
|
||||
await click("[data-trigger]");
|
||||
|
||||
assert
|
||||
.dom("[data-content]")
|
||||
.hasText("New account registrations for this period");
|
||||
.dom(".d-page-subheader .d-page-subheader__title")
|
||||
.hasText("Signups", "has a title");
|
||||
assert
|
||||
.dom(".d-page-subheader .d-page-subheader__description")
|
||||
.hasText(
|
||||
"New account registrations for this period",
|
||||
"has a description"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".admin-report-table thead tr th:first-child .title")
|
||||
|
@ -73,6 +73,10 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__full-width {
|
||||
flex: 1 0 100%;
|
||||
}
|
||||
|
||||
&__primary-content {
|
||||
flex: 0 1 70%;
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
.body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: var(--space-3);
|
||||
}
|
||||
|
||||
.main {
|
||||
@ -225,28 +226,32 @@
|
||||
}
|
||||
|
||||
.admin-reports-list {
|
||||
--d-border-radius: var(--space-0);
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
list-style-type: none;
|
||||
margin: 0 -1.5%;
|
||||
&__report {
|
||||
margin: 1.5%;
|
||||
border: 1px solid var(--primary-low);
|
||||
flex: 1 1 28%;
|
||||
min-width: 225px;
|
||||
max-width: 550px;
|
||||
a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 1em;
|
||||
.report-description {
|
||||
color: var(--primary-high);
|
||||
|
||||
&.admin-section-landing-wrapper {
|
||||
gap: 1em;
|
||||
padding-top: 0;
|
||||
|
||||
.admin-section-landing-item {
|
||||
margin-bottom: 0;
|
||||
padding: var(--space-4);
|
||||
border-radius: var(--d-border-radius);
|
||||
outline: 1px solid var(--primary-low);
|
||||
margin-bottom: 0;
|
||||
|
||||
@include breakpoint("mobile-extra-large", min-width) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border: 0;
|
||||
box-shadow: 0 0 0 1px var(--primary-300), 0 0 0 4px var(--primary-100);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5136,8 +5136,9 @@ en:
|
||||
|
||||
reports:
|
||||
title: "List of available reports"
|
||||
meta_doc: "Explore our <a href='https://meta.discourse.org/t/-/240233' rel='noopener noreferrer' target='_blank'>documentation</a> for a detailed overview of the reports."
|
||||
meta_doc: "Reports are a powerful tool to help you understand what’s happening on your site. They can help you identify trends, spot problems, and make decisions based on data."
|
||||
sidebar_title: "Reports"
|
||||
back: "Back to all reports"
|
||||
sidebar_link:
|
||||
all: "All reports"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user