UX: Apply admin UI to Badges (#28724)

* UX: Add a description about badges

* WIP: Apply admin UI guidelines

* FIX: Add routeModels to dbutton

Allows routeModels to be passed to a DButton along
with route, so we can use them as a LinkTo replacement
in more places.

Also fix up badges admin page header.

* UX: Reorder action buttons

* UX: Change header hierarchy to better align page's content structure

* UX: Update copy and remove unnecessary UI elements

* UX: Adjust header's icon spacing

* UX: Fix the header action buttons on mobile

* Apply prettier

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
This commit is contained in:
Ella E. 2024-09-04 20:18:23 -06:00 committed by GitHub
parent 06d749eadd
commit be5c37a6d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 78 additions and 84 deletions

View File

@ -6,6 +6,7 @@ export const AdminPageActionButton = <template>
...attributes ...attributes
@action={{@action}} @action={{@action}}
@route={{@route}} @route={{@route}}
@routeModels={{@routeModels}}
@label={{@label}} @label={{@label}}
@title={{@title}} @title={{@title}}
@icon={{@icon}} @icon={{@icon}}
@ -18,6 +19,7 @@ export const PrimaryButton = <template>
...attributes ...attributes
@action={{@action}} @action={{@action}}
@route={{@route}} @route={{@route}}
@routeModels={{@routeModels}}
@label={{@label}} @label={{@label}}
@title={{@title}} @title={{@title}}
@icon={{@icon}} @icon={{@icon}}
@ -30,6 +32,7 @@ export const DangerButton = <template>
...attributes ...attributes
@action={{@action}} @action={{@action}}
@route={{@route}} @route={{@route}}
@routeModels={{@routeModels}}
@label={{@label}} @label={{@label}}
@title={{@title}} @title={{@title}}
@icon={{@icon}} @icon={{@icon}}
@ -42,6 +45,7 @@ export const DefaultButton = <template>
...attributes ...attributes
@action={{@action}} @action={{@action}}
@route={{@route}} @route={{@route}}
@routeModels={{@routeModels}}
@label={{@label}} @label={{@label}}
@title={{@title}} @title={{@title}}
@icon={{@icon}} @icon={{@icon}}

View File

@ -1,22 +1,8 @@
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import { emojiUrlFor } from "discourse/lib/text"; import { emojiUrlFor } from "discourse/lib/text";
const badgeIntroLinks = [
{
text: "admin.badges.badge_intro.what_are_badges_title",
href: "https://meta.discourse.org/t/32540",
icon: "book",
},
{
text: "admin.badges.badge_intro.badge_query_examples_title",
href: "https://meta.discourse.org/t/18978",
icon: "book",
},
];
export default class AdminBadgesIndexRoute extends Route { export default class AdminBadgesIndexRoute extends Route {
setupController(controller) { setupController(controller) {
controller.badgeIntroLinks = badgeIntroLinks;
controller.badgeIntroEmoji = emojiUrlFor("woman_student:t4"); controller.badgeIntroEmoji = emojiUrlFor("woman_student:t4");
} }
} }

View File

@ -1,28 +1,39 @@
<div class="badges"> <div class="badges">
<div class="badges-header"> <AdminPageHeader
<h3 class="badges-heading">{{i18n "admin.badges.title"}}</h3> @titleLabel="admin.badges.title"
<div class="create-new-badge"> @descriptionLabel="admin.badges.description"
@learnMoreUrl="https://meta.discourse.org/t/understanding-and-using-badges/32540"
<LinkTo @route="adminBadges.award" @model="new" class="btn btn-default"> >
{{d-icon "upload"}} <:breadcrumbs>
<span class="d-button-label">{{i18n <DBreadcrumbsItem
"admin.badges.mass_award.title" @path="/admin/badges"
}}</span> @label={{i18n "admin.badges.title"}}
</LinkTo> />
</:breadcrumbs>
<DButton <:actions as |actions|>
@action={{route-action "editGroupings"}} <actions.Primary
@translatedLabel="Group settings" @route="adminBadges.show"
@icon="cog" @routeModels="new"
@class="btn-default edit-groupings-btn" @icon="plus"
@label="admin.badges.new"
/> />
<LinkTo @route="adminBadges.show" @model="new" class="btn btn-primary"> <actions.Default
{{d-icon "plus"}} @route="adminBadges.award"
<span>{{i18n "admin.badges.new"}}</span> @routeModels="new"
</LinkTo> @icon="upload"
</div> @label="admin.badges.mass_award.title"
</div> />
<actions.Default
@action={{routeAction "editGroupings"}}
@title="admin.badges.group_settings"
@label="admin.badges.group_settings"
@icon="cog"
class="edit-groupings-btn"
/>
</:actions>
</AdminPageHeader>
<div class="content-list"> <div class="content-list">
<ul class="admin-badge-list"> <ul class="admin-badge-list">
{{#each this.model as |badge|}} {{#each this.model as |badge|}}

View File

@ -1,5 +1,5 @@
<section class="award-badge"> <section class="award-badge">
<h1>{{i18n "admin.badges.mass_award.title"}}</h1> <h2>{{i18n "admin.badges.mass_award.title"}}</h2>
<p>{{i18n "admin.badges.mass_award.description"}}</p> <p>{{i18n "admin.badges.mass_award.description"}}</p>
{{#if this.model}} {{#if this.model}}

View File

@ -1,21 +1,4 @@
<section class="current-badges"> <section class="current-badge content-body">
<div class="badge-intro admin-intro"> <h2>{{i18n "admin.badges.badge_intro.title"}}</h2>
<img src={{this.badgeIntroEmoji}} class="badge-intro-emoji" alt="" /> <p>{{i18n "admin.badges.badge_intro.description"}}</p>
<div class="content-wrapper">
<h1>{{i18n "admin.badges.badge_intro.title"}}</h1>
<div class="external-resources">
{{#each this.badgeIntroLinks as |link|}}
<a
href={{link.href}}
class="external-link"
target="_blank"
rel="noopener noreferrer"
>
{{d-icon link.icon}}
<span>{{i18n link.text}}</span>
</a>
{{/each}}
</div>
</div>
</div>
</section> </section>

View File

@ -7,10 +7,10 @@
as |form data| as |form data|
> >
<h1 class="current-badge-header"> <h2 class="current-badge-header">
{{iconOrImage data}} {{iconOrImage data}}
<span class="badge-display-name">{{data.name}}</span> <span class="badge-display-name">{{data.name}}</span>
</h1> </h2>
<form.Field <form.Field
@name="enabled" @name="enabled"

View File

@ -103,7 +103,7 @@ export default class DButton extends GlimmerComponentWithDeprecatedParentView {
} }
_triggerAction(event) { _triggerAction(event) {
const { action: actionVal, route } = this.args; const { action: actionVal, route, routeModels } = this.args;
if (actionVal || route) { if (actionVal || route) {
if (actionVal) { if (actionVal) {
@ -134,7 +134,14 @@ export default class DButton extends GlimmerComponentWithDeprecatedParentView {
); );
} }
} else if (route) { } else if (route) {
this.router.transitionTo(route); if (routeModels) {
const routeModelsArray = Array.isArray(routeModels)
? routeModels
: [routeModels];
this.router.transitionTo(route, ...routeModelsArray);
} else {
this.router.transitionTo(route);
}
} }
event.preventDefault(); event.preventDefault();

View File

@ -3,8 +3,12 @@
&__title-row { &__title-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: stretch;
margin-bottom: 1em; margin-bottom: var(--space-2);
@media (max-width: $mobile-breakpoint) {
flex-direction: column;
}
h1, h1,
h3 { h3 {
@ -14,8 +18,20 @@
.admin-page-header__actions { .admin-page-header__actions {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end;
@media (max-width: $mobile-breakpoint) {
flex-direction: column;
}
button { button {
margin-left: 1em; margin-left: var(--space-2);
@media (max-width: $mobile-breakpoint) {
width: 100%;
margin-bottom: var(--space-2);
margin-left: 0;
}
} }
} }
} }

View File

@ -19,21 +19,8 @@
.content-list { .content-list {
flex: 0 0 27%; flex: 0 0 27%;
} }
.current-badges {
display: flex;
justify-content: center;
flex: 1 1 72%;
}
}
.badges-header {
padding: 10px 0;
border-top: 1px solid var(--primary-low);
border-bottom: 1px solid var(--primary-low);
.badges-heading {
margin: 0;
padding: 0 10px;
}
} }
.content-list { .content-list {
.admin-badge-list { .admin-badge-list {
height: 70vh; height: 70vh;
@ -67,7 +54,7 @@
.current-badge-header { .current-badge-header {
display: flex; display: flex;
gap: 1em; gap: 0.5em;
align-items: center; align-items: center;
font-size: var(--font-up-2-rem); font-size: var(--font-up-2-rem);
@ -77,7 +64,7 @@
} }
.d-icon { .d-icon {
font-size: 36px; font-size: var(--font-up-2-rem);
} }
.badge-display-name { .badge-display-name {

View File

@ -7017,9 +7017,10 @@ en:
name: Name name: Name
badge: Badge badge: Badge
display_name: Display Name display_name: Display Name
description: Description description: Badges reward users for their activities, contributions, and achievements to recognize, validate, and encourage positive behavior and engagement within the community.
long_description: Long description long_description: Long description
badge_type: Badge type badge_type: Badge type
group_settings: Group Settings
badge_grouping: Group badge_grouping: Group
badge_groupings: badge_groupings:
modal_title: Badge Groupings modal_title: Badge Groupings
@ -7084,9 +7085,8 @@ en:
with_post_time: <span class="username">%{username}</span> for post in %{link} at <span class="time">%{time}</span> with_post_time: <span class="username">%{username}</span> for post in %{link} at <span class="time">%{time}</span>
with_time: <span class="username">%{username}</span> at <span class="time">%{time}</span> with_time: <span class="username">%{username}</span> at <span class="time">%{time}</span>
badge_intro: badge_intro:
title: "Select an existing badge or create a new one to get started" title: "Choose a badge or create a new one"
what_are_badges_title: "What are badges?" description: "Start by selecting an existing badge to customize, or create a brand new badge"
badge_query_examples_title: "Badge query examples"
mass_award: mass_award:
title: Bulk Award title: Bulk Award
description: Award the same badge to many users at once. description: Award the same badge to many users at once.