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:
parent
06d749eadd
commit
be5c37a6d4
|
@ -6,6 +6,7 @@ export const AdminPageActionButton = <template>
|
|||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
|
@ -18,6 +19,7 @@ export const PrimaryButton = <template>
|
|||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
|
@ -30,6 +32,7 @@ export const DangerButton = <template>
|
|||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
|
@ -42,6 +45,7 @@ export const DefaultButton = <template>
|
|||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
|
|
|
@ -1,22 +1,8 @@
|
|||
import Route from "@ember/routing/route";
|
||||
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 {
|
||||
setupController(controller) {
|
||||
controller.badgeIntroLinks = badgeIntroLinks;
|
||||
controller.badgeIntroEmoji = emojiUrlFor("woman_student:t4");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,39 @@
|
|||
<div class="badges">
|
||||
<div class="badges-header">
|
||||
<h3 class="badges-heading">{{i18n "admin.badges.title"}}</h3>
|
||||
<div class="create-new-badge">
|
||||
|
||||
<LinkTo @route="adminBadges.award" @model="new" class="btn btn-default">
|
||||
{{d-icon "upload"}}
|
||||
<span class="d-button-label">{{i18n
|
||||
"admin.badges.mass_award.title"
|
||||
}}</span>
|
||||
</LinkTo>
|
||||
|
||||
<DButton
|
||||
@action={{route-action "editGroupings"}}
|
||||
@translatedLabel="Group settings"
|
||||
@icon="cog"
|
||||
@class="btn-default edit-groupings-btn"
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.badges.title"
|
||||
@descriptionLabel="admin.badges.description"
|
||||
@learnMoreUrl="https://meta.discourse.org/t/understanding-and-using-badges/32540"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/badges"
|
||||
@label={{i18n "admin.badges.title"}}
|
||||
/>
|
||||
</:breadcrumbs>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
@routeModels="new"
|
||||
@icon="plus"
|
||||
@label="admin.badges.new"
|
||||
/>
|
||||
|
||||
<LinkTo @route="adminBadges.show" @model="new" class="btn btn-primary">
|
||||
{{d-icon "plus"}}
|
||||
<span>{{i18n "admin.badges.new"}}</span>
|
||||
</LinkTo>
|
||||
</div>
|
||||
</div>
|
||||
<actions.Default
|
||||
@route="adminBadges.award"
|
||||
@routeModels="new"
|
||||
@icon="upload"
|
||||
@label="admin.badges.mass_award.title"
|
||||
/>
|
||||
|
||||
<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">
|
||||
<ul class="admin-badge-list">
|
||||
{{#each this.model as |badge|}}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<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>
|
||||
|
||||
{{#if this.model}}
|
||||
|
|
|
@ -1,21 +1,4 @@
|
|||
<section class="current-badges">
|
||||
<div class="badge-intro admin-intro">
|
||||
<img src={{this.badgeIntroEmoji}} class="badge-intro-emoji" alt="" />
|
||||
<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 class="current-badge content-body">
|
||||
<h2>{{i18n "admin.badges.badge_intro.title"}}</h2>
|
||||
<p>{{i18n "admin.badges.badge_intro.description"}}</p>
|
||||
</section>
|
|
@ -7,10 +7,10 @@
|
|||
as |form data|
|
||||
>
|
||||
|
||||
<h1 class="current-badge-header">
|
||||
<h2 class="current-badge-header">
|
||||
{{iconOrImage data}}
|
||||
<span class="badge-display-name">{{data.name}}</span>
|
||||
</h1>
|
||||
</h2>
|
||||
|
||||
<form.Field
|
||||
@name="enabled"
|
||||
|
|
|
@ -103,7 +103,7 @@ export default class DButton extends GlimmerComponentWithDeprecatedParentView {
|
|||
}
|
||||
|
||||
_triggerAction(event) {
|
||||
const { action: actionVal, route } = this.args;
|
||||
const { action: actionVal, route, routeModels } = this.args;
|
||||
|
||||
if (actionVal || route) {
|
||||
if (actionVal) {
|
||||
|
@ -134,7 +134,14 @@ export default class DButton extends GlimmerComponentWithDeprecatedParentView {
|
|||
);
|
||||
}
|
||||
} 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();
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
&__title-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1em;
|
||||
align-items: stretch;
|
||||
margin-bottom: var(--space-2);
|
||||
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
h1,
|
||||
h3 {
|
||||
|
@ -14,8 +18,20 @@
|
|||
.admin-page-header__actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 1em;
|
||||
margin-left: var(--space-2);
|
||||
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
width: 100%;
|
||||
margin-bottom: var(--space-2);
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,21 +19,8 @@
|
|||
.content-list {
|
||||
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 {
|
||||
.admin-badge-list {
|
||||
height: 70vh;
|
||||
|
@ -67,7 +54,7 @@
|
|||
|
||||
.current-badge-header {
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
gap: 0.5em;
|
||||
align-items: center;
|
||||
font-size: var(--font-up-2-rem);
|
||||
|
||||
|
@ -77,7 +64,7 @@
|
|||
}
|
||||
|
||||
.d-icon {
|
||||
font-size: 36px;
|
||||
font-size: var(--font-up-2-rem);
|
||||
}
|
||||
|
||||
.badge-display-name {
|
||||
|
|
|
@ -7017,9 +7017,10 @@ en:
|
|||
name: Name
|
||||
badge: Badge
|
||||
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
|
||||
badge_type: Badge type
|
||||
group_settings: Group Settings
|
||||
badge_grouping: Group
|
||||
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_time: <span class="username">%{username}</span> at <span class="time">%{time}</span>
|
||||
badge_intro:
|
||||
title: "Select an existing badge or create a new one to get started"
|
||||
what_are_badges_title: "What are badges?"
|
||||
badge_query_examples_title: "Badge query examples"
|
||||
title: "Choose a badge or create a new one"
|
||||
description: "Start by selecting an existing badge to customize, or create a brand new badge"
|
||||
mass_award:
|
||||
title: Bulk Award
|
||||
description: Award the same badge to many users at once.
|
||||
|
|
Loading…
Reference in New Issue