Add test connection feature for database targets
This commit introduces a new endpoint to test database connection. The frontend now includes a button to test the connection before creating a target, with real-time feedback on success or failure. Related styles and components were updated for better user experience.
This commit is contained in:
@@ -20,6 +20,7 @@ export function TargetsPage() {
|
||||
const [form, setForm] = useState(emptyForm);
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [testState, setTestState] = useState({ loading: false, message: "", ok: null });
|
||||
|
||||
const canManage = me?.role === "admin" || me?.role === "operator";
|
||||
|
||||
@@ -50,6 +51,31 @@ export function TargetsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const testConnection = async () => {
|
||||
setTestState({ loading: true, message: "", ok: null });
|
||||
try {
|
||||
const result = await apiFetch(
|
||||
"/targets/test-connection",
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
host: form.host,
|
||||
port: form.port,
|
||||
dbname: form.dbname,
|
||||
username: form.username,
|
||||
password: form.password,
|
||||
sslmode: form.sslmode,
|
||||
}),
|
||||
},
|
||||
tokens,
|
||||
refresh
|
||||
);
|
||||
setTestState({ loading: false, message: `${result.message} (PostgreSQL ${result.server_version})`, ok: true });
|
||||
} catch (e) {
|
||||
setTestState({ loading: false, message: String(e.message || e), ok: false });
|
||||
}
|
||||
};
|
||||
|
||||
const deleteTarget = async (id) => {
|
||||
if (!confirm("Delete target?")) return;
|
||||
try {
|
||||
@@ -66,7 +92,7 @@ export function TargetsPage() {
|
||||
{error && <div className="card error">{error}</div>}
|
||||
|
||||
{canManage && (
|
||||
<details className="card collapsible" open>
|
||||
<details className="card collapsible">
|
||||
<summary className="collapse-head">
|
||||
<div>
|
||||
<h3>New Target</h3>
|
||||
@@ -111,9 +137,17 @@ export function TargetsPage() {
|
||||
</small>
|
||||
</div>
|
||||
<div className="field submit-field">
|
||||
<button className="primary-btn">Create target</button>
|
||||
<div className="target-actions">
|
||||
<button type="button" className="secondary-btn" onClick={testConnection} disabled={testState.loading}>
|
||||
{testState.loading ? "Testing..." : "Test connection"}
|
||||
</button>
|
||||
<button className="primary-btn">Create target</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{testState.message && (
|
||||
<div className={`test-connection-result ${testState.ok ? "ok" : "fail"}`}>{testState.message}</div>
|
||||
)}
|
||||
</details>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user