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 Component from "@glimmer/component";
|
||||||
import icon from "discourse-common/helpers/d-icon";
|
|
||||||
import { i18n } from "discourse-i18n";
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
export default class WebhookStatus extends Component {
|
export default class WebhookStatus extends Component {
|
||||||
iconNames = ["far-circle", "circle-xmark", "circle", "circle"];
|
statusClasses = ["--inactive", "--critical", "--success", "--inactive"];
|
||||||
iconClasses = ["text-muted", "text-danger", "text-successful", "text-muted"];
|
|
||||||
|
|
||||||
get status() {
|
get status() {
|
||||||
const lastStatus = this.args.webhook.get("last_delivery_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}`);
|
return i18n(`admin.web_hooks.delivery_status.${this.status.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
get iconName() {
|
get statusClass() {
|
||||||
return this.iconNames[this.status.id - 1];
|
return this.statusClasses[this.status.id - 1];
|
||||||
}
|
|
||||||
|
|
||||||
get iconClass() {
|
|
||||||
return this.iconClasses[this.status.id - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
{{icon this.iconName class=this.iconClass}}
|
<div role="status" class="status-label {{this.statusClass}}">
|
||||||
|
<div class="status-label-indicator">
|
||||||
|
</div>
|
||||||
|
<div class="status-label-text">
|
||||||
{{this.deliveryStatus}}
|
{{this.deliveryStatus}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,19 +14,34 @@
|
||||||
|
|
||||||
{{#if this.model}}
|
{{#if this.model}}
|
||||||
<LoadMore @selector=".web-hooks tr" @action={{this.loadMore}}>
|
<LoadMore @selector=".web-hooks tr" @action={{this.loadMore}}>
|
||||||
<table class="web-hooks grid">
|
<table class="d-admin-table web-hooks">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{i18n "admin.web_hooks.delivery_status.title"}}</th>
|
|
||||||
<th>{{i18n "admin.web_hooks.payload_url"}}</th>
|
<th>{{i18n "admin.web_hooks.payload_url"}}</th>
|
||||||
<th>{{i18n "admin.web_hooks.description_label"}}</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>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{#each this.model as |webhook|}}
|
{{#each this.model as |webhook|}}
|
||||||
<tr>
|
<tr class="d-admin-row__content">
|
||||||
<td class="delivery-status">
|
<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}}>
|
<LinkTo @route="adminWebHooks.show" @model={{webhook}}>
|
||||||
<WebhookStatus
|
<WebhookStatus
|
||||||
@deliveryStatuses={{this.deliveryStatuses}}
|
@deliveryStatuses={{this.deliveryStatuses}}
|
||||||
|
@ -34,13 +49,8 @@
|
||||||
/>
|
/>
|
||||||
</LinkTo>
|
</LinkTo>
|
||||||
</td>
|
</td>
|
||||||
<td class="payload-url">
|
<td class="d-admin-row__controls controls">
|
||||||
<LinkTo @route="adminWebHooks.edit" @model={{webhook}}>
|
<div class="d-admin-row__controls-options">
|
||||||
{{webhook.payload_url}}
|
|
||||||
</LinkTo>
|
|
||||||
</td>
|
|
||||||
<td class="description">{{webhook.description}}</td>
|
|
||||||
<td class="controls">
|
|
||||||
<LinkTo
|
<LinkTo
|
||||||
@route="adminWebHooks.edit"
|
@route="adminWebHooks.edit"
|
||||||
@model={{webhook}}
|
@model={{webhook}}
|
||||||
|
@ -56,6 +66,7 @@
|
||||||
@title="delete"
|
@title="delete"
|
||||||
class="destroy btn-danger"
|
class="destroy btn-danger"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -33,7 +33,7 @@ module("Integration | Component | webhook-status", function (hooks) {
|
||||||
assert.dom().hasText("Failed");
|
assert.dom().hasText("Failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("iconName", async function (assert) {
|
test("statusLabelClass", async function (assert) {
|
||||||
const webhook = new CoreFabricators(getOwner(this)).webhook();
|
const webhook = new CoreFabricators(getOwner(this)).webhook();
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<WebhookStatus
|
<WebhookStatus
|
||||||
|
@ -42,30 +42,18 @@ module("Integration | Component | webhook-status", function (hooks) {
|
||||||
/>
|
/>
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
assert.dom(".d-icon-far-circle").exists();
|
assert.dom(".status-label").hasClass("--inactive");
|
||||||
|
|
||||||
webhook.set("last_delivery_status", 2);
|
webhook.set("last_delivery_status", 2);
|
||||||
|
|
||||||
await rerender();
|
await rerender();
|
||||||
|
assert.dom(".status-label").hasClass("--critical");
|
||||||
|
|
||||||
assert.dom(".d-icon-circle-xmark").exists();
|
webhook.set("last_delivery_status", 3);
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
await rerender();
|
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;
|
$mobile-breakpoint: 700px;
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--space-1: 0.25rem;
|
--space-0: 0.125rem; //2px
|
||||||
|
--space-1: 0.25rem; //4px
|
||||||
--space-2: calc(0.25rem * 2);
|
--space-2: calc(0.25rem * 2);
|
||||||
--space-3: calc(0.25rem * 3);
|
--space-3: calc(0.25rem * 3);
|
||||||
--space-4: calc(0.25rem * 4);
|
--space-4: calc(0.25rem * 4);
|
||||||
|
|
|
@ -67,25 +67,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default
|
||||||
.status-label {
|
.status-label {
|
||||||
--d-border-radius: var(--space-4);
|
--d-border-radius: var(--space-4);
|
||||||
|
--status-icon-diameter: 8px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
background-color: var(--primary-low);
|
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);
|
border-radius: var(--d-border-radius);
|
||||||
|
|
||||||
.status-label-indicator {
|
.status-label-indicator {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 6px;
|
width: var(--status-icon-diameter);
|
||||||
height: 6px;
|
height: var(--status-icon-diameter);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: var(--primary-high);
|
background-color: var(--primary-high);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-right: var(--space-1);
|
margin-right: var(--space-1);
|
||||||
margin-top: 0.4rem;
|
margin-top: 0.35rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-label-text {
|
.status-label-text {
|
||||||
|
@ -93,6 +95,45 @@
|
||||||
font-size: var(--font-down-1);
|
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 {
|
.d-admin-row__overview {
|
||||||
|
|
|
@ -1,45 +1,25 @@
|
||||||
// Styles for admin/api
|
// Styles for admin/api
|
||||||
|
|
||||||
table.web-hooks.grid {
|
.d-admin-table.web-hooks {
|
||||||
td.delivery-status {
|
.d-admin-row__overview.payload-url {
|
||||||
div {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.d-icon {
|
|
||||||
margin-right: 0.25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
td.payload-url {
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
max-width: 55vw;
|
max-width: 20vw;
|
||||||
|
|
||||||
|
@include breakpoint(medium) {
|
||||||
|
max-width: 70vw;
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
td.controls {
|
.d-admin-row__detail.description {
|
||||||
text-align: right;
|
@include breakpoint(medium) {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.d-admin-row__mobile-label {
|
||||||
|
@include breakpoint(medium) {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@include breakpoint(mobile-extra-large) {
|
|
||||||
tbody {
|
|
||||||
tr {
|
|
||||||
grid-template-columns: 0.5fr 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
td.controls {
|
|
||||||
grid-row: 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue