UX: Use admin table classes for Calendar Holidays list (#34942)

Followup a5730bfe2f

Apply admin table UI guidelines, and convert
AdminHolidaysListItem to a glimmer component.
This commit is contained in:
Martin Brennan
2025-09-24 17:13:50 +10:00
committed by GitHub
parent 1b013a2c21
commit 7daea6d77d
8 changed files with 80 additions and 82 deletions
@@ -1,86 +1,69 @@
/* eslint-disable ember/no-classic-components */
import Component from "@ember/component";
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { classNameBindings, tagName } from "@ember-decorators/component";
import DButton from "discourse/components/d-button";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
@tagName("tr")
@classNameBindings("isHolidayDisabled:disabled")
export default class AdminHolidaysListItem extends Component {
loading = false;
isHolidayDisabled = false;
@tracked loading = false;
@tracked isHolidayDisabled = this.args.isHolidayDisabled || false;
@action
async disableHoliday() {
async toggleEnableHoliday() {
if (this.loading) {
return;
}
this.set("loading", true);
let url, type;
if (this.isHolidayDisabled) {
url = `/admin/discourse-calendar/holidays/enable`;
type = "DELETE";
} else {
url = `/admin/discourse-calendar/holidays/disable`;
type = "POST";
}
this.loading = true;
try {
await ajax({
url: `/admin/discourse-calendar/holidays/disable`,
type: "POST",
url,
type,
data: {
disabled_holiday: {
holiday_name: this.holiday.name,
region_code: this.region_code,
holiday_name: this.args.holiday.name,
region_code: this.args.regionCode,
},
},
});
this.set("isHolidayDisabled", true);
this.isHolidayDisabled = !this.isHolidayDisabled;
} catch (error) {
popupAjaxError(error);
} finally {
this.set("loading", false);
}
}
@action
async enableHoliday() {
if (this.loading) {
return;
}
this.set("loading", true);
try {
await ajax({
url: `/admin/discourse-calendar/holidays/enable`,
type: "DELETE",
data: {
disabled_holiday: {
holiday_name: this.holiday.name,
region_code: this.region_code,
},
},
});
this.set("isHolidayDisabled", false);
} catch (error) {
popupAjaxError(error);
} finally {
this.set("loading", false);
this.loading = false;
}
}
<template>
<td>{{this.holiday.date}}</td>
<td>{{this.holiday.name}}</td>
<td>
{{#if this.isHolidayDisabled}}
<DButton
@action={{this.enableHoliday}}
@label="discourse_calendar.enable_holiday"
/>
{{else}}
<DButton
@action={{this.disableHoliday}}
@label="discourse_calendar.disable_holiday"
/>
{{/if}}
</td>
<tr class="d-table__row {{if this.isHolidayDisabled '--disabled'}}">
<td class="d-table__cell --detail">{{@holiday.date}}</td>
<td class="d-table__cell --detail">{{@holiday.name}}</td>
<td class="d-table__cell --controls">
<div class="d-table__cell-actions">
<DButton
@action={{this.toggleEnableHoliday}}
@label={{if
this.isHolidayDisabled
"discourse_calendar.enable_holiday"
"discourse_calendar.disable_holiday"
}}
@isLoading={{this.loading}}
class="btn-default btn-small"
/>
</div>
</td>
</tr>
</template>
}
@@ -2,20 +2,22 @@ import { i18n } from "discourse-i18n";
import AdminHolidaysListItem from "./admin-holidays-list-item";
const AdminHolidaysList = <template>
<table class="holidays-list">
<thead>
<tr>
<td>{{i18n "discourse_calendar.date"}}</td>
<td colspan="2">{{i18n "discourse_calendar.holiday"}}</td>
<table class="d-table admin-holidays-list">
<thead class="d-table__header">
<tr class="d-table__row">
<th class="d-table__header-cell">{{i18n "discourse_calendar.date"}}</th>
<th class="d-table__header-cell">{{i18n
"discourse_calendar.holiday"
}}</th>
<th></th>
</tr>
</thead>
<tbody>
<tbody class="d-table__body">
{{#each @holidays as |holiday|}}
<AdminHolidaysListItem
@holiday={{holiday}}
@isHolidayDisabled={{holiday.disabled}}
@region_code={{@region_code}}
@regionCode={{@regionCode}}
/>
{{/each}}
</tbody>
@@ -11,6 +11,7 @@ import { HOLIDAY_REGIONS } from "../lib/regions";
@selectKitOptions({
filterable: true,
allowAny: false,
none: "discourse_calendar.region.select_region",
})
@pluginApiIdentifiers("timezone-input")
@classNames("timezone-input", "region-input")
@@ -31,7 +31,7 @@ export default RouteTemplate(
{{#if @controller.holidays}}
<AdminHolidaysList
@holidays={{@controller.holidays}}
@region_code={{@controller.selectedRegion}}
@regionCode={{@controller.selectedRegion}}
/>
{{/if}}
</div>
@@ -1,9 +1,17 @@
@use "lib/viewport";
.region-input {
width: 50%;
@include viewport.until(md) {
width: 100%;
}
}
.disabled td {
background-color: var(--primary-very-low);
color: var(--primary-medium);
font-style: italic;
.admin-holidays-list {
.d-table__row.--disabled td {
background-color: var(--primary-very-low);
color: var(--primary-medium);
font-style: italic;
}
}
@@ -39,6 +39,7 @@ en:
title: "Region"
none: "None"
use_current_region: "Use Current Region"
select_region: "Select a region..."
names:
ae: "United Arab Emirates"
ar: "Argentina"
@@ -61,17 +61,17 @@ acceptance("Admin - Discourse Calendar - Holidays", function (needs) {
await settled();
assert
.dom(".holidays-list")
.dom(".admin-holidays-list")
.includesText("New Year's Day", "it displays holiday names");
assert
.dom(".holidays-list")
.dom(".admin-holidays-list")
.includesText("Good Friday", "it displays holiday names");
assert
.dom(".holidays-list")
.dom(".admin-holidays-list")
.includesText("2022-01-01", "it displays holiday dates");
assert
.dom(".holidays-list")
.dom(".admin-holidays-list")
.includesText("2022-04-15", "it displays holiday dates");
});
@@ -87,16 +87,16 @@ acceptance("Admin - Discourse Calendar - Holidays", function (needs) {
assert
.dom("table tbody tr")
.hasClass(
"disabled",
"after clicking the disable button, it adds a .disabled CSS class"
"--disabled",
"after clicking the disable button, it adds a .--disabled CSS class"
);
await click("table tr.disabled button");
await click("table tr.--disabled button");
assert
.dom("table tbody tr")
.doesNotHaveClass(
"disabled",
"after clicking the enable button, it removes the .disabled CSS class"
"--disabled",
"after clicking the enable button, it removes the .--disabled CSS class"
);
});
});
@@ -3,7 +3,7 @@ import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import AdminHolidaysListItem from "discourse/plugins/discourse-calendar/discourse/components/admin-holidays-list-item";
module("Integration | Component | admin-holidays-list-item", function (hooks) {
module("Integration | Component | AdminHolidaysListItem", function (hooks) {
setupRenderingTest(hooks);
test("when a holiday is disabled, it displays an enable button and adds a disabled CSS class", async function (assert) {
@@ -27,7 +27,7 @@ module("Integration | Component | admin-holidays-list-item", function (hooks) {
);
assert.dom("button").hasText("Enable", "it displays an enable button");
assert.dom("tr").hasClass("disabled", "it adds a 'disabled' CSS class");
assert.dom("tr").hasClass("--disabled", "it adds a '--disabled' CSS class");
});
test("when a holiday is enabled, it displays a disable button and does not add a disabled CSS class", async function (assert) {
@@ -53,6 +53,9 @@ module("Integration | Component | admin-holidays-list-item", function (hooks) {
assert.dom("button").hasText("Disable", "it displays a disable button");
assert
.dom("tr")
.doesNotHaveClass("disabled", "it does not add a 'disabled' CSS class");
.doesNotHaveClass(
"--disabled",
"it does not add a '--disabled' CSS class"
);
});
});