UX: Apply admin table to webhooks (#30317)
* UX: Apply admin table classes for consistent mobile styling on the web hooks page * DEV: Remove icon on the status component; update status classes * DEV: Update tests for webhook status component * DEV: add space var with a smaller value * DEV: Add styling for different status labels
This commit is contained in:
parent
e04f535601
commit
37f032752e
|
@ -1,10 +1,8 @@
|
|||
import Component from "@glimmer/component";
|
||||
import icon from "discourse-common/helpers/d-icon";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class WebhookStatus extends Component {
|
||||
iconNames = ["far-circle", "circle-xmark", "circle", "circle"];
|
||||
iconClasses = ["text-muted", "text-danger", "text-successful", "text-muted"];
|
||||
statusClasses = ["--inactive", "--critical", "--success", "--inactive"];
|
||||
|
||||
get status() {
|
||||
const lastStatus = this.args.webhook.get("last_delivery_status");
|
||||
|
@ -15,16 +13,17 @@ export default class WebhookStatus extends Component {
|
|||
return i18n(`admin.web_hooks.delivery_status.${this.status.name}`);
|
||||
}
|
||||
|
||||
get iconName() {
|
||||
return this.iconNames[this.status.id - 1];
|
||||
}
|
||||
|
||||
get iconClass() {
|
||||
return this.iconClasses[this.status.id - 1];
|
||||
get statusClass() {
|
||||
return this.statusClasses[this.status.id - 1];
|
||||
}
|
||||
|
||||
<template>
|
||||
{{icon this.iconName class=this.iconClass}}
|
||||
{{this.deliveryStatus}}
|
||||
<div role="status" class="status-label {{this.statusClass}}">
|
||||
<div class="status-label-indicator">
|
||||
</div>
|
||||
<div class="status-label-text">
|
||||
{{this.deliveryStatus}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
|
|
|
@ -14,19 +14,34 @@
|
|||
|
||||
{{#if this.model}}
|
||||
<LoadMore @selector=".web-hooks tr" @action={{this.loadMore}}>
|
||||
<table class="web-hooks grid">
|
||||
<table class="d-admin-table web-hooks">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{i18n "admin.web_hooks.delivery_status.title"}}</th>
|
||||
<th>{{i18n "admin.web_hooks.payload_url"}}</th>
|
||||
<th>{{i18n "admin.web_hooks.description_label"}}</th>
|
||||
<th>{{i18n "admin.web_hooks.controls"}}</th>
|
||||
<th>{{i18n "admin.web_hooks.delivery_status.title"}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each this.model as |webhook|}}
|
||||
<tr>
|
||||
<td class="delivery-status">
|
||||
<tr class="d-admin-row__content">
|
||||
<td class="d-admin-row__overview payload-url">
|
||||
<LinkTo @route="adminWebHooks.edit" @model={{webhook}}>
|
||||
{{webhook.payload_url}}
|
||||
</LinkTo>
|
||||
</td>
|
||||
<td class="d-admin-row__detail description">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.web_hooks.description_label"}}
|
||||
</div>
|
||||
{{webhook.description}}
|
||||
</td>
|
||||
<td class="d-admin-row__detail delivery-status">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.web_hooks.delivery_status.title"}}
|
||||
</div>
|
||||
|
||||
<LinkTo @route="adminWebHooks.show" @model={{webhook}}>
|
||||
<WebhookStatus
|
||||
@deliveryStatuses={{this.deliveryStatuses}}
|
||||
|
@ -34,28 +49,24 @@
|
|||
/>
|
||||
</LinkTo>
|
||||
</td>
|
||||
<td class="payload-url">
|
||||
<LinkTo @route="adminWebHooks.edit" @model={{webhook}}>
|
||||
{{webhook.payload_url}}
|
||||
</LinkTo>
|
||||
</td>
|
||||
<td class="description">{{webhook.description}}</td>
|
||||
<td class="controls">
|
||||
<LinkTo
|
||||
@route="adminWebHooks.edit"
|
||||
@model={{webhook}}
|
||||
class="btn btn-default no-text"
|
||||
title={{i18n "admin.web_hooks.edit"}}
|
||||
>
|
||||
{{d-icon "far-pen-to-square"}}
|
||||
</LinkTo>
|
||||
<td class="d-admin-row__controls controls">
|
||||
<div class="d-admin-row__controls-options">
|
||||
<LinkTo
|
||||
@route="adminWebHooks.edit"
|
||||
@model={{webhook}}
|
||||
class="btn btn-default no-text"
|
||||
title={{i18n "admin.web_hooks.edit"}}
|
||||
>
|
||||
{{d-icon "far-pen-to-square"}}
|
||||
</LinkTo>
|
||||
|
||||
<DButton
|
||||
@action={{fn this.destroyWebhook webhook}}
|
||||
@icon="xmark"
|
||||
@title="delete"
|
||||
class="destroy btn-danger"
|
||||
/>
|
||||
<DButton
|
||||
@action={{fn this.destroyWebhook webhook}}
|
||||
@icon="xmark"
|
||||
@title="delete"
|
||||
class="destroy btn-danger"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
|
|
@ -33,7 +33,7 @@ module("Integration | Component | webhook-status", function (hooks) {
|
|||
assert.dom().hasText("Failed");
|
||||
});
|
||||
|
||||
test("iconName", async function (assert) {
|
||||
test("statusLabelClass", async function (assert) {
|
||||
const webhook = new CoreFabricators(getOwner(this)).webhook();
|
||||
await render(<template>
|
||||
<WebhookStatus
|
||||
|
@ -42,30 +42,18 @@ module("Integration | Component | webhook-status", function (hooks) {
|
|||
/>
|
||||
</template>);
|
||||
|
||||
assert.dom(".d-icon-far-circle").exists();
|
||||
assert.dom(".status-label").hasClass("--inactive");
|
||||
|
||||
webhook.set("last_delivery_status", 2);
|
||||
|
||||
await rerender();
|
||||
assert.dom(".status-label").hasClass("--critical");
|
||||
|
||||
assert.dom(".d-icon-circle-xmark").exists();
|
||||
});
|
||||
|
||||
test("iconClass", async function (assert) {
|
||||
const webhook = new CoreFabricators(getOwner(this)).webhook();
|
||||
await render(<template>
|
||||
<WebhookStatus
|
||||
@deliveryStatuses={{DELIVERY_STATUSES}}
|
||||
@webhook={{webhook}}
|
||||
/>
|
||||
</template>);
|
||||
|
||||
assert.dom(".d-icon").hasClass("text-muted");
|
||||
|
||||
webhook.set("last_delivery_status", 2);
|
||||
|
||||
webhook.set("last_delivery_status", 3);
|
||||
await rerender();
|
||||
assert.dom(".status-label").hasClass("--success");
|
||||
|
||||
assert.dom(".d-icon").hasClass("text-danger");
|
||||
webhook.set("last_delivery_status", 4);
|
||||
await rerender();
|
||||
assert.dom(".status-label").hasClass("--inactive");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
$mobile-breakpoint: 700px;
|
||||
|
||||
:root {
|
||||
--space-1: 0.25rem;
|
||||
--space-0: 0.125rem; //2px
|
||||
--space-1: 0.25rem; //4px
|
||||
--space-2: calc(0.25rem * 2);
|
||||
--space-3: calc(0.25rem * 3);
|
||||
--space-4: calc(0.25rem * 4);
|
||||
|
|
|
@ -67,25 +67,27 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Default
|
||||
.status-label {
|
||||
--d-border-radius: var(--space-4);
|
||||
--status-icon-diameter: 8px;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
width: fit-content;
|
||||
background-color: var(--primary-low);
|
||||
padding: var(--space-1) var(--space-2);
|
||||
padding: var(--space-0) var(--space-2);
|
||||
border-radius: var(--d-border-radius);
|
||||
|
||||
.status-label-indicator {
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
width: var(--status-icon-diameter);
|
||||
height: var(--status-icon-diameter);
|
||||
border-radius: 50%;
|
||||
background-color: var(--primary-high);
|
||||
flex-shrink: 0;
|
||||
margin-right: var(--space-1);
|
||||
margin-top: 0.4rem;
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.status-label-text {
|
||||
|
@ -93,6 +95,45 @@
|
|||
font-size: var(--font-down-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Success badge
|
||||
.status-label.--success {
|
||||
background-color: var(--success-low);
|
||||
|
||||
.status-label-indicator {
|
||||
background-color: var(--success);
|
||||
}
|
||||
|
||||
.status-label-text {
|
||||
color: var(--success-hover);
|
||||
}
|
||||
}
|
||||
|
||||
// Critical badge
|
||||
.status-label.--critical {
|
||||
background-color: var(--danger-low);
|
||||
|
||||
.status-label-indicator {
|
||||
background-color: var(--danger);
|
||||
}
|
||||
|
||||
.status-label-text {
|
||||
color: var(--danger-hover);
|
||||
}
|
||||
}
|
||||
|
||||
// Inactive badge
|
||||
.status-label.--inactive {
|
||||
background-color: var(--primary-low);
|
||||
|
||||
.status-label-indicator {
|
||||
background-color: var(--primary-high);
|
||||
}
|
||||
|
||||
.status-label-text {
|
||||
color: var(--primary-high);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.d-admin-row__overview {
|
||||
|
|
|
@ -1,44 +1,24 @@
|
|||
// Styles for admin/api
|
||||
|
||||
table.web-hooks.grid {
|
||||
td.delivery-status {
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.d-icon {
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
}
|
||||
td.payload-url {
|
||||
.d-admin-table.web-hooks {
|
||||
.d-admin-row__overview.payload-url {
|
||||
word-wrap: break-word;
|
||||
max-width: 55vw;
|
||||
}
|
||||
td.controls {
|
||||
display: flex;
|
||||
button {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 550px) {
|
||||
tbody {
|
||||
tr {
|
||||
grid-template-columns: 0.5fr repeat(2, 1fr) 0.5fr;
|
||||
}
|
||||
max-width: 20vw;
|
||||
|
||||
td.controls {
|
||||
text-align: right;
|
||||
}
|
||||
@include breakpoint(medium) {
|
||||
max-width: 70vw;
|
||||
}
|
||||
}
|
||||
@include breakpoint(mobile-extra-large) {
|
||||
tbody {
|
||||
tr {
|
||||
grid-template-columns: 0.5fr 1fr;
|
||||
}
|
||||
|
||||
.d-admin-row__detail.description {
|
||||
@include breakpoint(medium) {
|
||||
display: block;
|
||||
}
|
||||
td.controls {
|
||||
grid-row: 2;
|
||||
|
||||
.d-admin-row__mobile-label {
|
||||
@include breakpoint(medium) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue