Add template variables display and SMTP settings UI updates
All checks were successful
PostgreSQL Compatibility Matrix / PG14 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG15 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG16 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG17 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG18 smoke (push) Successful in 7s

This commit introduces a new section for template variables in the Admin Users page, improving clarity by listing placeholders available for email templates. It also enhances the SMTP settings interface with clearer organization and additional features like clearing stored passwords. Associated styling updates include new visual elements for template variables and subcards.
This commit is contained in:
2026-02-12 16:37:31 +01:00
parent c437e72c2b
commit 8e5a549c2c
2 changed files with 200 additions and 135 deletions

View File

@@ -2,6 +2,21 @@ import React, { useEffect, useState } from "react";
import { apiFetch } from "../api";
import { useAuth } from "../state";
const TEMPLATE_VARIABLES = [
"target_name",
"target_id",
"alert_name",
"severity",
"category",
"description",
"message",
"value",
"warning_threshold",
"alert_threshold",
"checked_at",
"alert_key",
];
export function AdminUsersPage() {
const { tokens, refresh, me } = useAuth();
const [users, setUsers] = useState([]);
@@ -223,6 +238,9 @@ export function AdminUsersPage() {
</div>
{smtpInfo && <div className="test-connection-result ok">{smtpInfo}</div>}
<form className="grid two admin-smtp-form" onSubmit={saveSmtp}>
<div className="admin-subcard field-full">
<h4>SMTP Settings</h4>
<div className="grid two">
<label className="toggle-check field-full">
<input
type="checkbox"
@@ -286,7 +304,8 @@ export function AdminUsersPage() {
onChange={(e) => setEmailSettings({ ...emailSettings, from_email: e.target.value })}
/>
</div>
<div className="admin-field">
<div className="admin-field field-full">
<label>Transport mode</label>
<div className="smtp-mode-picker" role="radiogroup" aria-label="SMTP transport mode">
<button
@@ -316,13 +335,33 @@ export function AdminUsersPage() {
</div>
<small className="muted">Select exactly one mode to avoid STARTTLS/SSL conflicts.</small>
</div>
<div className="admin-field">
<label>Template variables</label>
<small className="muted">
Use placeholders like: {"{target_name}"}, {"{alert_name}"}, {"{severity}"}, {"{description}"}, {"{message}"}, {"{value}"}, {"{warning_threshold}"}, {"{alert_threshold}"}, {"{checked_at}"}, {"{alert_key}"}
</small>
<label className="toggle-check field-full">
<input
type="checkbox"
checked={emailSettings.clear_smtp_password}
onChange={(e) => setEmailSettings({ ...emailSettings, clear_smtp_password: e.target.checked, smtp_password: e.target.checked ? "" : emailSettings.smtp_password })}
/>
<span className="toggle-ui" />
<span>Clear stored SMTP password</span>
</label>
</div>
</div>
<div className="admin-subcard field-full">
<h4>Template Settings</h4>
<p className="muted template-help-text">
If a template field is left empty, NexaPG automatically uses the built-in default template.
</p>
<div className="template-vars-grid">
{TEMPLATE_VARIABLES.map((item) => (
<code key={item} className="template-var-pill">
{"{" + item + "}"}
</code>
))}
</div>
<div className="grid two">
<div className="admin-field field-full">
<label>Warning subject template</label>
<input
@@ -355,16 +394,8 @@ export function AdminUsersPage() {
onChange={(e) => setEmailSettings({ ...emailSettings, alert_body_template: e.target.value })}
/>
</div>
<label className="toggle-check field-full">
<input
type="checkbox"
checked={emailSettings.clear_smtp_password}
onChange={(e) => setEmailSettings({ ...emailSettings, clear_smtp_password: e.target.checked, smtp_password: e.target.checked ? "" : emailSettings.smtp_password })}
/>
<span className="toggle-ui" />
<span>Clear stored SMTP password</span>
</label>
</div>
</div>
<div className="form-actions field-full">
<input

View File

@@ -1208,6 +1208,40 @@ td {
gap: 10px;
}
.admin-subcard {
border: 1px solid #2c598f;
border-radius: 12px;
padding: 12px;
background: linear-gradient(180deg, #102748, #0e2342);
}
.admin-subcard h4 {
margin: 0 0 8px 0;
font-size: 18px;
}
.template-help-text {
margin: 0 0 10px 0;
}
.template-vars-grid {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 10px;
}
.template-var-pill {
display: inline-flex;
align-items: center;
border-radius: 999px;
border: 1px solid #4d81bc;
background: #15365f;
color: #d9ebff;
padding: 4px 10px;
font-size: 12px;
}
.admin-test-recipient {
min-width: 260px;
max-width: 320px;